题目地址:http://121.36.145.157:8044,访问得到页面内容如下所示:
根据返回内容我们可以得知,该Web地址有两个文件:
我们可以逐一访问来一探究竟,第一个文件展示当前PHP环境的一些配置信息http://121.36.145.157:8044/phpinfo.php
:
第二个文件带有一个请求参数url
,该参数默认展示的值是看雪CTF战队的头像地址:
此处可能有SSRF,于是猜测可能是考SSRF+Redis,内网探测了一波无果。
思考一下,既然此处有SSRF会不会存在文件读取呢?读取文件之前我们先判断当前服务器是Linux / Windows,可以使用请求路径的大小写判断(Linux大小写敏感,Windows大小写不敏感。),分别请求如下地址:
根据访问结果判断当前是Linux系统,所以尝试使用file:///etc/passwd
带入带url
参数值中请求:
返回结果提示host
为空的,这就是说后端可能有一个判断host
的逻辑,因为在file
协议加入host
不影响使用,所以我们可以修改下请求值为file://127.0.0.1/etc/passwd
,成功获取到passwd文件的内容:
接着根据之前/phpinfo.php
文件返回的配置信息,知道当前网站路径为/var/www/html
,所以我们可以尝试读取当前的url.php
文件(参数值为file://127.0.0.1/var/www/html/url.php
):
至此,我们得到了PHP文件源码,接着就是看逻辑找缺陷。从代码逻辑上看,就是获取请求参数值,根据parse_url
函数去解析之,接着取解析后的host
判断是否是127.0.0.1
、localhost
、ctf.pediy.com
,如果是,则使用curl进行请求,并返回请求的结果。
并且在代码中的注释也提示了我们,要想获取flag就要去请求如下这个地址:
而这个地址是限制了IP访问的(尝试请求头伪造啥的都无法绕过):
所以我们需要通过这个SSRF去请求到该地址才能知道该地址的文件内容获取Flag。
这种搭配很眼熟,想到使用parse_url
函数和curl
的解析差异去满足host
值判断逻辑,并且curl
还能去请求到Flag所在的目标地址:
但是这里却用不了,看了下这类Tricks是有指定的curl
版本的,根据/phpinfo.php
返回的内容告诉我们,这并不满足目标版本:
但是根据代码所知这个方向肯定没问题,所以我们需要自己去构建满足逻辑的差异解析值。
所以我也尝试使用Fuzz的方式去找到结果:
但最终都没有成功,所以回归本质,我们知道URL的组成格式如下:
根据前辈们所实践出来的结果,它们一直在都处在中间层user:pass@host:port
去绕过,那么有没有一种可能,我们不需要完全满足URL的格式呢?尝试了很多结果,最终发现如下值,成功绕开逻辑并且使得curl
访问到目标Flag机器:
我们根据返回结果可以得知,请求到了123.57.254.42
,并且请求的是/127.0.0.1
路径,所以我们可以跨目录的形式去请求flag.php
:
成功获取到Flag:
接着我们来理一理,这是为什么可以绕过去,从parse_url
函数角度去看这个值:
而从curl
角度则是这样的:
由于没有scheme,则自动补全使用http://
。
所以,最后我们知道正是因为这种实现的差异化导致了本题目所表达的问题。
<!
-
-
phpinfo.php
-
-
>
<img src
=
"url.php?url=https://ctf.pediy.com/upload/team/762/team236762.png"
>
<!
-
-
phpinfo.php
-
-
>
<img src
=
"url.php?url=https://ctf.pediy.com/upload/team/762/team236762.png"
>
/
phpinfo.php
/
url.php?url
=
/
phpinfo.php
/
url.php?url
=
http:
/
/
121.36
.
145.157
:
8044
/
url.php
-
> 返回
200
http:
/
/
121.36
.
145.157
:
8044
/
urL.php
-
> 返回
404
http:
/
/
121.36
.
145.157
:
8044
/
url.php
-
> 返回
200
http:
/
/
121.36
.
145.157
:
8044
/
urL.php
-
> 返回
404
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课