UEditor 1.4.3.3的SSRF漏洞

产生漏洞的代码片段: ueditor\php\Uploader.class.php

private function saveRemote()
{
    $imgUrl = htmlspecialchars($this->fileField);
    $imgUrl = str_replace("&", "&", $imgUrl);

    //http开头验证 如果不是的话 就return
    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] : '';

    // 判断是否是合法 url
    if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) {
        $this->stateInfo = $this->getStateInfo("INVALID_URL");
        return;
    }

    preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches);
    $host_without_protocol = count($matches) > 1 ? $matches[1] : '';

    // 此时提取出来的可能是 ip 也有可能是域名,先获取 ip
    $ip = gethostbyname($host_without_protocol);
    // 判断是否是私有 ip
    if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
        $this->stateInfo = $this->getStateInfo("INVALID_IP");
echo "<br>判断是否是私有 ip<br>";
        return;
    }
    //获取请求头并检测死链
    $heads = get_headers($imgUrl, 1);
    if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
        $this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK");
        return;
    }
    //格式验证(扩展名验证和Content-Type验证)
    $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();
    ...省略...

检测流程:
1、http开头验证
2、判断是否是合法 url
3、判断是否是私有 ip
4、获取请求头并检测死链
5、格式验证(扩展名验证和Content-Type验证)

PHP FILTER_VALIDATE_IP 过滤器:

FILTER_FLAG_IPV4 - 要求值是合法的 IPv4 IP(比如 255.255.255.255FILTER_FLAG_IPV6 - 要求值是合法的 IPv6 IP(比如	2001:0db8:85a3:08d3:1319:8a2e:0370:7334FILTER_FLAG_NO_PRIV_RANGE - 要求值是 RFC 指定的私域 IP (比如 192.168.0.1FILTER_FLAG_NO_RES_RANGE - 要求值不在保留的 IP 范围内。该标志接受 IPV4IPV6 值。

两种方法可以绕过:
1、正则绕过

在第五步检测之前 唯一起到限制的就是preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches);,那么就说明我们只要绕过这条正则表达就可以了,那么其实就是一个正常的URL。

2、利用DNS重绑定

参考文章:
http://admintony.com/UEditor-1-4-3-3-SSRF-AND-DNS-rebinding-attack.html

http://www.bendawang.site/2017/05/31/%E5%85%B3%E4%BA%8EDNS-rebinding%E7%9A%84%E6%80%BB%E7%BB%93/

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值