1.7.7 任务安全与权限控制

本节聚焦计划任务的安全风险与权限边界,强调“最小权限、可审计、可回滚”的原则,避免任务被滥用、提权或引发系统级故障。

文章图片

一、权限模型与运行身份
- 明确运行用户,避免默认 root
- 业务任务使用专用账号 + 最小化 sudo 规则。
- 系统级任务放置于 /etc/cron.*/etc/crontab 并标明执行用户。

示例:创建专用账号与最小化 sudo

# 创建专用账号
useradd -r -s /sbin/nologin appjob
# 仅允许执行备份脚本
cat >/etc/sudoers.d/appjob <<'EOF'
appjob ALL=(root) NOPASSWD: /usr/local/bin/backup.sh
EOF
chmod 440 /etc/sudoers.d/appjob
# 解释:仅放行 backup.sh,禁止 NOPASSWD: ALL

二、访问控制与白名单
- 通过 /etc/cron.allow/etc/cron.deny 限制 cron 使用者,推荐白名单。
- at 同理:/etc/at.allow/etc/at.deny

示例:启用 cron 白名单

# 仅允许 appjob 与 ops 用户使用 cron
printf "appjob\nops\n" >/etc/cron.allow
# 清空 deny 以避免冲突
: > /etc/cron.deny

# 解释:
# cron.allow 存在时,只有其中用户可使用 cron

三、脚本与配置文件安全
- 脚本集中放置,最小权限:chmod 750
- 避免明文密码,使用受限权限配置文件。
- 避免危险通配符,做路径校验。

示例:安全脚本与权限

mkdir -p /opt/scripts
chown appjob:appjob /opt/scripts
chmod 750 /opt/scripts

cat >/opt/scripts/cleanup.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
TARGET="/data/tmp"
# 路径校验
[[ "$TARGET" == /data/tmp ]] || exit 1
find "$TARGET" -type f -mtime +7 -print -delete
EOF

chmod 750 /opt/scripts/cleanup.sh
# 解释:
# set -euo pipefail 防止未定义变量/管道错误
# 校验固定路径,避免误删

四、环境变量与路径风险
- 任务中显式设置 PATH,使用绝对路径。
- 外部输入必须校验,严禁直接拼接执行。

示例:安全 crontab

# 以 appjob 用户添加
crontab -u appjob -e
# 每天 02:00 清理临时文件
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 2 * * * /opt/scripts/cleanup.sh >> /var/log/cleanup.log 2>&1

命令解释:
- PATH=...:避免执行到恶意同名命令
- >> /var/log/cleanup.log 2>&1:标准输出/错误输出统一入日志

五、日志与审计
- 任务日志重定向,保留可审计记录。
- 建议安装 auditd 监控关键文件改动。

安装与启用 auditd

# RHEL/CentOS
yum install -y audit
systemctl enable --now auditd

# Ubuntu/Debian
apt-get update && apt-get install -y auditd
systemctl enable --now auditd

示例:审计脚本目录

auditctl -w /opt/scripts -p wa -k cron_scripts
# 解释:监控写入(w)与属性变更(a),关键字 cron_scripts

ausearch -k cron_scripts --start today

六、systemd 定时器的安全优势
- 可限定用户与文件访问范围,增强隔离。

示例:systemd 定时器

# /etc/systemd/system/cleanup.service
[Unit]
Description=Safe cleanup job

[Service]
Type=oneshot
User=appjob
Group=appjob
ExecStart=/opt/scripts/cleanup.sh
NoNewPrivileges=true
ProtectSystem=full
ReadWritePaths=/data/tmp
# /etc/systemd/system/cleanup.timer
[Unit]
Description=Run cleanup daily

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now cleanup.timer
systemctl list-timers | grep cleanup

七、提权与误操作防护
- 严格限制 sudo 规则。
- 关键任务加入锁文件,避免重入。

示例:锁文件机制

cat >/opt/scripts/report.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
LOCK=/var/lock/report.lock
exec 9>"$LOCK"
flock -n 9 || exit 0
/usr/local/bin/generate_report
EOF
chmod 750 /opt/scripts/report.sh

八、典型风险与防范要点
- 脚本被篡改 → 审计 + 只读权限 + 版本控制
- 任务被隐藏 → 定期巡检 /etc/cron* 与用户 crontab -l
- root 任务拼接外部输入 → 加白名单校验

巡检示例

# 列出系统级计划任务
ls -l /etc/cron.* /etc/crontab
# 列出所有用户 crontab
for u in $(cut -d: -f1 /etc/passwd); do
  crontab -u "$u" -l 2>/dev/null | sed "s/^/[$u] /"
done

九、常见故障排查
- 任务未执行:检查 cron 服务状态、时间/时区、文件权限
- 无日志:检查重定向路径权限、脚本是否执行
- 权限不足:检查 sudoers 与脚本文件属主

排查命令

systemctl status cron || systemctl status crond
timedatectl
ls -l /opt/scripts/cleanup.sh /var/log/cleanup.log
journalctl -u cron --since "today"

十、练习
1. 创建 appjob 用户并配置白名单,仅允许其使用 cron。
2. 编写一个安全备份脚本,使用绝对路径与锁文件机制。
3. 使用 auditd 监控 /opt/scripts 目录并验证审计日志。
4. 将 cron 任务改为 systemd timer,启用 ProtectSystem=full 并验证只读限制。