首页
社区
课程
招聘
[原创]2022KCTF春季赛-第四题-飞蛾扑火-Writeup
2022-5-17 09:50 9775

[原创]2022KCTF春季赛-第四题-飞蛾扑火-Writeup

2022-5-17 09:50
9775

题目地址:http://121.36.145.157:8044,访问得到页面内容如下所示:

 

图片描述

1
2
<!--phpinfo.php-->
<img src="url.php?url=https://ctf.pediy.com/upload/team/762/team236762.png">

根据返回内容我们可以得知,该Web地址有两个文件:

1
2
/phpinfo.php
/url.php?url=

我们可以逐一访问来一探究竟,第一个文件展示当前PHP环境的一些配置信息http://121.36.145.157:8044/phpinfo.php

 

图片描述

 

第二个文件带有一个请求参数url,该参数默认展示的值是看雪CTF战队的头像地址:

 

图片描述

 

此处可能有SSRF,于是猜测可能是考SSRF+Redis,内网探测了一波无果。

 

思考一下,既然此处有SSRF会不会存在文件读取呢?读取文件之前我们先判断当前服务器是Linux / Windows,可以使用请求路径的大小写判断(Linux大小写敏感,Windows大小写不敏感。),分别请求如下地址:

1
2
http://121.36.145.157:8044/url.php -> 返回200
http://121.36.145.157:8044/urL.php -> 返回404

根据访问结果判断当前是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.1localhostctf.pediy.com,如果是,则使用curl进行请求,并返回请求的结果。

 

并且在代码中的注释也提示了我们,要想获取flag就要去请求如下这个地址:

1
//echo curl_request("http://123.57.254.42/flag.php","get",[],true,5);//get flag

而这个地址是限制了IP访问的(尝试请求头伪造啥的都无法绕过):

 

图片描述

 

所以我们需要通过这个SSRF去请求到该地址才能知道该地址的文件内容获取Flag。

 

这种搭配很眼熟,想到使用parse_url函数和curl的解析差异去满足host值判断逻辑,并且curl还能去请求到Flag所在的目标地址:

1
2
http://u:p@123.57.254.42@127.0.0.1/
http://123.57.254.42#@127.0.0.1/

但是这里却用不了,看了下这类Tricks是有指定的curl版本的,根据/phpinfo.php返回的内容告诉我们,这并不满足目标版本:

 

图片描述

 

但是根据代码所知这个方向肯定没问题,所以我们需要自己去构建满足逻辑的差异解析值。

 

所以我也尝试使用Fuzz的方式去找到结果:

1
2
3
http://123.57.254.42{%00-%FF}{%00-%FF}127.0.0.1/
http://123.57.254.42{%00-%FF}127.0.0.1{%00-%FF}
...

但最终都没有成功,所以回归本质,我们知道URL的组成格式如下:

1
scheme://user:pass@host:port/path?query

根据前辈们所实践出来的结果,它们一直在都处在中间层user:pass@host:port去绕过,那么有没有一种可能,我们不需要完全满足URL的格式呢?尝试了很多结果,最终发现如下值,成功绕开逻辑并且使得curl访问到目标Flag机器:

1
123.57.254.42://127.0.0.1

图片描述

 

我们根据返回结果可以得知,请求到了123.57.254.42,并且请求的是/127.0.0.1路径,所以我们可以跨目录的形式去请求flag.php

1
123.57.254.42://127.0.0.1/../flag.php

成功获取到Flag:

 

图片描述

 

接着我们来理一理,这是为什么可以绕过去,从parse_url函数角度去看这个值:

1
2
3
123.57.254.42 -> scheme
127.0.0.1 -> host
../flag.php -> path

而从curl角度则是这样的:

1
2
123.57.254.42 -> host
/127.0.0.1/../flag.php -> path

由于没有scheme,则自动补全使用http://

 

所以,最后我们知道正是因为这种实现的差异化导致了本题目所表达的问题。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞11
打赏
分享
最新回复 (1)
雪    币: 1556
活跃值: (3897)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
_DriverEntry 2022-5-18 09:23
2
0
学习
游客
登录 | 注册 方可回帖
返回