Linux应急基础排查技巧
本文主要面向安全运营人员、运维人员、应急响应服务交付人员,介绍当Linux服务器失陷后如何开展应急响应排查,包括网络、进程、权限维持、文件、用户等、日志方面排查方法。
Linux应急基础排查技巧
本文主要面向安全运营人员、运维人员、应急响应服务交付人员,介绍当Linux服务器失陷后如何开展应急响应排查,包括网络、进程、权限维持、文件、用户等、日志方面排查方法。
01 网络排查
已建立的网络连接排查
首先应该排查已建立的网络连接,可能服务器上存在后门程序通过反向连接攻击者C2服务器被攻击者持续控制,推荐优先采用ss命令,部分老版本Linux发行版可采用netstat命令,用法如下:
# 查看已经建立的TCP连接
ss -natulp state established
netstat -natlp | grep ESTA如下图,存在和192.168.66.104:444端口创建的网络连接,该连接为msf的反向连接
下图为端口扫描特征,一个进程和外部大量IP和端口存在建立连接:
开放端口
查看开放端口有助于了解服务器存在哪些服务,这些服务可能是攻击者的入口,可以为后续溯源提供排查方向。可以使用ss/netstat查看开放端口,用法如下:
netstat -nautlp | grep LISTEN
ss -natulp | grep LISTEN如下图为某服务器端口开放情况,从下图信息可知22、80、443、8080、10000端口均对外开放,其中80、443端口为nginx开放端口,其他绑定到本地环回的端口可能被反向代理从而间接开放,服务器可能失陷的原因为ssh被成功暴力破解登录或web应用存在漏洞:
02 进程排查
进程异常是最常见的主机被入侵痕迹之一,常见异常现象包括资源占用过高、进程存在异常外连、进程路径异常。
进程资源占用排查
可以通过top命令按 CPU 和内存占用排序排查进程资源占用,并记录进程ID。常用快捷键:
快捷键 | 作用 |
| 按内存占用排序 |
| 按CPU占用排序 |
| 设置刷新时间 |
| 结束进程 |
以下为top命令输出实例:
如果怀疑服务器感染挖矿病毒、卡顿,可以优先排查资源占用情况。
注:库文件劫持、rootkit可能隐藏或篡改服务器信息,但这两种情况不在本文介绍范围中
进程路径排查
根据进程ID排查进程可执行文件路径
如果通过前期通过网络连接排查到异常进程,并获取到进程ID,可以根据进程ID获取进程可执行文件路径:
/proc/[pid]/exe
可以通过以下命令排查进程更多信息,例如执行命令时所在目录:
ls -al /proc/[pid]排查所有进程可执行路径
通过以下命令列出所有进程ID、命令、参数、文件路径,重点关注异常路径下的进程,比如/tmp、各隐藏目录等:
ps -eo pid,comm,args,exe如下,观察到一个进程在/tmp目录下,高度可疑:
如果某些版本ps不支持exe参数,使用:
ps -eo pid,comm,args | while read pid comm args; do
case "$pid" in
PID|''|[0-9]*) : ;;
*) continue ;;
esac
exe=$(readlink -f /proc/$pid/exe 2>/dev/null || echo '-')
printf '%s\t%s\t%s\t%s\n' "$pid" "$comm" "$exe" "$args"
done排查进程执行树
如果该Linux发行版使用systemd,可以通过以下命令查看进程相关信息:
systemctl status [进程ID]
如果系统有pstree,也可以通过以下方式获取执行树信息:
ps -ef
如果什么都没有,使用以下命令创建脚本,通过遍历/proc目录树获取进程信息:
cat > ./proc_ancestors << 'EOF'
#!/bin/bash
pid=${1:-$$}
while [ "$pid" -gt 0 ] && [ -d /proc/$pid ]; do
ppid=$(awk -F'\t' '/^PPid:/{print $2}' /proc/$pid/status)
exe=$(readlink -f /proc/$pid/exe 2>/dev/null || echo '-')
cmd=$(tr '\0' ' ' </proc/$pid/cmdline 2>/dev/null)
printf 'PID=%-6s PPID=%-6s EXE=%-30s CMD=%s\n' "$pid" "$ppid" "$exe" "$cmd"
pid=$ppid
done
EOF
chmod +x ./proc_ancestors执行:
./proc_ancestors [pid]如下所示,从下往上是进程的树状关系:
其他进程排查技巧
# 搜索指定进程pid
pgrep [进程名一部分]
# 查看文件被删除但仍在运行的进程
lsof +L1 | grep ' txt ' | grep -vE ' (mem|DEL)'异常进程处置
# 结束某个进程
kill -9 [完整进程名]
# 结束某个程序的所有进程
killall [程序名]
# 批量结束firefox相关进程
kill -9 $(pgrep firefox)03 权限维持排查
攻击者如果想要长期控制一台服务器,会采用一些权限维持手法来启用后门程序,常见的权限维持手法包括:登录即执行、开机自启、定时触发。
Shell 环境配置脚本
攻击者通过在 shell 配置文件中植入后门,实现用户登录时自动执行:
~/.bashrc
/etc/bashrc
/etc/bash.bashrc文件名 | 作用范围 | 主要作用与描述 |
| 用户级 | 当前登录用户专属的配置文件,用于定义个人环境变量、别名、Shell函数和自定义脚本提示符等 |
| 系统级 | 为所有用户提供全局的Bash Shell设置,通常包含系统范围的别名和函数,常见于RHEL、CentOS、Fedora等系统 |
| 系统级 | 功能同 |
通过以下命令可以遍历所有用户.bashrc文件,通过less命令进行查看:
for user in $(cat /etc/passwd | cut -d: -f1);do echo "###/home/$user/.bashrc###";sudo cat /home/$user/.bashrc 2>/dev/null ;done | less
通过以下命令可以查看全局bashrc文件:
cat /etc/bashrc /etc/bash.bashrc通过以下命令可以在所有用户bashrc文件检索特定字符串:
for user in $(cat /etc/passwd | cut -d: -f1);do echo "========/home/$user/.bashrc========";sudo grep -rn [要检索的字符串] /home/$user/.bashrc 2>/dev/null ;done例如检索恶意文件名msf_66.104_4444.elf字符串,检索到在 /home/ops/.bashrc文件的第7行存在:
用户环境初始化配置文件
用户登录系统时会自动执行几个 profile 脚本文件,用于会话初始化操作,如设置环境变量、启动程序、定义别名和函数。攻击者可能将后门程序写入这些 profile 中以进行权限维持:
~/.profile
~/.bash_profile
/etc/profile
文件名 | 作用范围 | 主要作用与描述 | 触发时机 |
| 系统级 | 为所有用户提供全局的登录Shell配置,系统管理员在这里设置全局环境变量(如 | 用户登录系统时(仅一次) |
| 用户级 | 当前登录用户专属的登录Shell配置文件,用于设置个人环境变量和启动程序,常见于RHEL、CentOS、Fedora等系统 | 用户登录系统时(仅一次) |
| 用户级 | 功能类似 | 用户登录系统时(仅一次) |
排查方法和前面一致,不再贴示例图,以下是常用命令:
# 查看所有用户.profile
for user in $(cat /etc/passwd | cut -d: -f1);do echo "###/home/$user/.profile###";sudo cat /home/$user/.profile 2>/dev/null ;done
# 查看全局profile
cat /etc/profile
# 在所有用户.profile中检索指定字符串
for user in $(cat /etc/passwd | cut -d: -f1);do sudo grep -rn 【要检索的字符串】 /home/$user/.profile /home/$user/.bash_profile 2>/dev/null ;done
# 示例:在所有用户profile中检索msf字符串
for user in $(cat /etc/passwd | cut -d: -f1);do sudo grep -rn msf /home/$user/.profile /home/$user/.bash_profile 2>/dev/null ;done
自启动服务和初始化脚本
当前主流 Linux 发行版采用 systemd 管理服务,可以通过 systemctl 对开机自启动服务进行排查:
systemctl list-unit-files | grep enabled部分老旧系统采用 System V init 和 Upstart 管理服务,所以相关路径都需要进行排查:
# 需要排查的路径
/etc/systemd/system/
/etc/inittab
/usr/lib/systemd/system/
/etc/init/
/etc/rc.d/
/etc/rc.local初始化系统 | 典型发行版 | 核心配置文件/目录 | 系统初始化脚本 | 用户自定义启动方式 |
System V init | CentOS 6、RHEL 6、Debian 7及更早版本 |
|
|
|
systemd | CentOS 7+/RHEL 7+、Ubuntu 16.04+、Debian 8+(现代主流发行版) |
|
| 自定义 |
Upstart | Ubuntu 9.10至14.10、CentOS 6 |
|
|
|
# 在服务相关路径中搜索指定字符串
grep -rn "字符串" /etc/systemd/system/* /etc/inittab /usr/lib/systemd/system/* /etc/init/* /etc/rc.d/* /etc/rc.local计划任务
# 通过crontab命令查看计划任务(不推荐,容易遗漏)
crontab -l # 列出当前用户计划任务详细内容
crontab -l -u user # 列出指定用户计划任务需要注意的是,如果计划任务中包含\r (回车符), 会导致 crontab -l 输出时覆盖前面的内容,导致crontab -l输出不可见,所以计划任务排查建议通过 find 命令手动查看以下位置的计划任务:
/var/spool/cron/*
/var/spool/anacron/*
/etc/crontab
/etc/cron.d/*
/etc/cron.daily/*
/etc/cron.hourly/*
/etc/cron.monthly/*
/etc/cron.weekly/*
/etc/anacrontab可以通过以下命令查看所有计划任务:
( \
echo "===== /etc/crontab ====="; cat /etc/crontab 2>/dev/null; \
echo -e "\n===== /etc/anacrontab ====="; cat /etc/anacrontab 2>/dev/null; \
echo -e "\n===== /var/spool/cron ====="; \
for f in /var/spool/cron/*; do [ -f "$f" ] && echo -e "\n--- $f ---" && cat "$f"; done; \
echo -e "\n===== /var/spool/anacron ====="; \
for f in /var/spool/anacron/*; do [ -f "$f" ] && echo -e "\n--- $f ---" && cat "$f"; done; \
echo -e "\n===== /etc/cron.d ====="; \
for f in /etc/cron.d/*; do [ -f "$f" ] && echo -e "\n--- $f ---" && cat "$f"; done; \
echo -e "\n===== /etc/cron.hourly ====="; ls -l /etc/cron.hourly/ 2>/dev/null; \
echo -e "\n===== /etc/cron.daily ====="; ls -l /etc/cron.daily/ 2>/dev/null; \
echo -e "\n===== /etc/cron.weekly ====="; ls -l /etc/cron.weekly/ 2>/dev/null; \
echo -e "\n===== /etc/cron.monthly ====="; ls -l /etc/cron.monthly/ 2>/dev/null; \
)或者使用 grep -rn在这些计划任务目录和文件检索指定字符串:
grep -rn "[检索字符串]" /var/spool/cron/ /var/spool/anacron/ /etc/crontab /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ /etc/cron.monthly/ /etc/cron.weekly/ /etc/anacrontab恶意计划任务处置
确认恶意计划任务后的处置方式:
# 使用编辑器编辑当前的crontab文件
crontab -e
# 删除指定计划任务
sed -i '/str/d' file
# 删除所有计划任务(谨慎操作)
crontab -r
# vim 编辑计划任务文件
vim [计划任务文件]04 文件排查
可执行程序排查
新版本find命令支持 -executable 参数,可以使用以下命令进行排查
# 排查近期修改的可执行程序
find [目录列表] -type f -executable -mtime -1 -exec ls -l {} \; 2>/dev/null这里只用/tmp目录做演示,可以看到成功排查出刻意放置的文件:

老版本可以使用下面命令进行检索(兼容性高,新版本一样可以使用)
find [目录列表] -type f -mtime -7 \( -perm -u=x -o -perm -g=x -o -perm -o=x \)排查某文件状态
可以使用 stat 命令排查文件状态,包括修改时间
stat [filename]排查某时间段修改文件排查
# 排查指定时间范围内被修改过的文件
find [路径列表] -type f -newermt '2026-08-21 08:00:00' ! -newermt '2026-08-22 17:00:00' 2>/dev/null
# 排查某时间范围的文件(按修改时间排序,最新在前)
find [路径列表] -type f -newermt '2026-08-21 08:00:00' ! -newermt '2026-08-22 17:00:00' -printf "%T@ %Tc %p\n" | sort -nrfind 命令时间参数说明:
%T@:文件的最后修改时间(mtime),以Unix时间戳(秒+小数部分)表示,如1689456789.123456789%Tc:文件的最后修改时间,格式化为可读的日期时间,如Mon Jul 17 14:33:09 2023%p:文件的完整路径
文件完整性排查
部分病毒程序会修改或替换 netstat、ps、top 等常见系统命令,以实现权限维持或回显信息隐藏。对比文件 MD5 值和修改时间,主要有两种方式。
第一种使用 md5sum 校验关键文件,并将 MD5 值放到威胁情报平台检索或者与正常同版本软件包文件对比:
md5sum [文件]如果系统是RPM系,可以使用rpm -Va 检测(RPM 系):
rpm -Va该命令本质上也是对比文件的 MD5 值,校验时取本地文件的 MD5 值,然后和库里面的值进行校验,如果有改变则判断为变化,则会有标志位。
输出参数含义:
标志 | 含义 |
| 文件长度发生了变化 |
| 文件的访问权限或文件类型发生了变化 |
| MD5校验和发生了变化 |
| 设备节点的属性发生了变化 |
| 文件的符号链接发生了变化 |
| 文件/子目录/设备节点的owner发生了变化 |
| 文件/子目录/设备节点的group发生了变化 |
| 文件最后一次的修改时间发生了变化 |

05 用户排查
用户信息排查
账户排查
# 查看所有账户
cat /etc/passwd | cut -d: -f1
# 查看超级用户(UID为0的用户)
awk -F: '$3==0 {print $1}' /etc/passwd发现多个异常账户:
账户登录失败排查
排查近期登录失败信息:
lastb可以看到192.168.66.105短时间内多次登录root账户失败,疑似暴力破解:
所有用户最后一次登录时间排查
查看所有用户最后的登录信息,如果有异常用户登录信息,则可以给大致入侵时间提供参考:
lastlog当前用户
排查当前用户近期登录,看是否有陌生IP或者异常时间的登录记录:
last # 数据来自/var/log/wtmp、/var/log/btmp、/var/log/utmp 
空口令账户排查
# 查看空口令账户
awk -F: '$2==0 {print $1}' /etc/shadow公钥登录排查
将 SSH 公钥写入用户家目录下的 .ssh/authorized_keys 文件中可无需密码登录服务器,攻击者可能写入自己的公钥实现对服务器的长期访问:
# SSH公钥排查
ls -al /root/.ssh/
cat /root/.ssh/authorized_keys
# 排查所有用户公钥写入情况
for user in $(cat /etc/passwd | cut -d: -f1);do echo "========/home/$user/.ssh/authorized_keys========";sudo cat /home/$user/.ssh/authorized_keys 2>/dev/null ;done用户管理
# 切换账户
su
# 锁定账户(解锁用-u)
passwd -l user
# 删除账号
userdel [用户名]06 日志排查
历史命令排查
以下主要针对 bash,服务器也极少使用其他 shell:
# 历史下载的脚本(通过wget/curl下载的后缀为.sh/.pl/.py的脚本)
more /root/.bash_history | grep -E "((wget|curl).*\.(sh|pl|py))" | grep -v grep
# 历史增加的账号
history | egrep "(useradd|groupadd)" | grep -v grep
# 历史是否删除过账号
history | egrep "(userdel|groupdel)" | grep -v grep
# 查看所有用户所有类型shell的可疑命令执行记录
sudo find /home /root -type f \( -name ".bash_history" -o -name ".zsh_history" -o -name ".sh_history" -o -name ".history" -o -path "*/.local/share/fish/fish_history" \) -exec echo -e "\n===== {} =====\n" \; -exec sh -c 'cat {} | grep -E "curl|useradd|userdel|whoami|ifconfig|vim|sh|python|wget|frp|kill" | grep -v grep' \;其他常见 shell 命令历史记录文件名:
.sh_history(ksh).history(csh).bash_history(bash).zsh_history(zsh)
身份认证和授权日志分析
身份验证和授权相关日志存储在 /var/log/secure 和 /var/log/auth.log 中,这两个文件在功能上完全相同:
- RHEL/CentOS/Fedora/Rocky Linux/AlmaLinux 等基于 Red Hat 的发行版使用
/var/log/secure - Debian/Ubuntu/Linux Mint 等基于 Debian 的发行版使用
/var/log/auth.log
# 查看SSH登录成功日志
grep -E "Accepted (password|publickey)" /var/log/secure* /var/log/auth*
# 查看SSH登录失败日志
grep "Failed password" /var/log/secure* /var/log/auth*
# 查看新增用户
grep "new user" /var/log/secure* /var/log/auth* | awk -F '[=,]' '{print $1,$2}' | awk '{print $1,$2,$3,$9}'查看定时下载任务
计划任务日志存储在 /var/log/cron 开头的文件中,可以结合 grep 进行筛选:
more /var/log/cron* | grep "wget\|curl"