Skip to content

Go 主机安全面试:Cron 与 at 定时任务持久化检测

Linux 主机被入侵后,攻击者不一定注册 systemd 服务,也可能写入 cron、at、anacron 或用户级定时任务,让后门周期执行、下载脚本或低频反连。面试官通常会追问:Go Agent 怎么采集这些配置?怎么判断异常?怎么避免把正常运维任务误报成攻击?

岗位场景

text
cron / at / anacron 配置
  -> Agent 扫描系统级和用户级任务入口
  -> 解析执行时间、执行用户、命令、脚本路径和环境变量
  -> 关联文件落地、进程启动、网络外连和历史基线
  -> 识别异常定时任务、低频后门和持久化线索
  -> 输出可复盘证据

这类题考的是 Linux 定时任务机制、文件系统取证、命令解析、误报治理和 Go 侧低开销扫描能力。

高频面试题

1. 为什么 HIDS/EDR 要关注 cron 和 at?

简洁答案:cron 和 at 都能让命令在未来自动执行,攻击者可以用它们维持权限、周期下载 payload 或延迟触发反弹 shell。

关键知识点:

  • cron 适合周期执行,at 适合一次性延迟执行。
  • 攻击者常把命令藏在用户 crontab、/etc/cron.d/var/spool/cron 或脚本目录里。
  • 低频任务不一定立刻产生进程事件,配置落地本身就是重要证据。

Go 落地思路:

  • 同时采集系统级目录和用户级 spool,不只看 /etc/crontab
  • 任务事件至少包含 task_pathuserschedulecommandmtimeowner
  • 把配置事件和后续进程、文件、网络事件关联,避免孤立判断。

2. Linux 上常见定时任务入口有哪些?

简洁答案:重点看系统 crontab、/etc/cron.*、用户 crontab spool、anacron 配置和 at 队列。

常见入口:

text
/etc/crontab
/etc/cron.d/
/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/
/var/spool/cron/
/var/spool/cron/crontabs/
/etc/anacrontab
/var/spool/at/

关键知识点:

  • 不同发行版的用户 crontab 路径可能不同。
  • /etc/cron.d 格式通常包含执行用户,用户 crontab 通常不包含用户字段。
  • cron.hourly 这类目录里可能是脚本,检测时要读取脚本元信息和摘要。

Go 落地思路:

  • 用固定目录白名单扫描,不递归全盘。
  • 目录不存在是正常情况,记录一次环境信息即可。
  • 对单文件大小设上限,避免异常大文件拖慢 Agent。
go
func isCronEntry(path string) bool {
	return strings.Contains(path, "/cron") || strings.Contains(path, "/anacron") || strings.Contains(path, "/at")
}

3. 可疑 cron 任务通常有哪些特征?

简洁答案:重点看可写目录执行、解释器拉脚本、下载执行、base64 解码、反弹 shell 和伪装命名。

典型特征:

  • 命令包含 curlwgetbash -cpython -cperl -ebase64 -d
  • 执行文件来自 /tmp/dev/shm/var/tmp、Web 上传目录或普通用户隐藏目录。
  • 任务名伪装成系统维护任务,但路径、属主或 hash 不可信。
  • 计划频率异常,例如每分钟执行下载脚本或每小时尝试外连。
  • 修改时间接近 Web RCE、提权或异常登录时间。

Go 落地思路:

  • 先用命令形态和路径做候选筛选,再补充 hash、属主、权限和文件来源。
  • 输出命中原因,例如 download_executetemp_pathreverse_shell_token
  • 不要只靠字符串黑名单,至少关联用户、父目录权限和历史基线。

4. Go Agent 如何解析 crontab,避免一上来写复杂解析器?

简洁答案:安全检测先稳定抽取注释、环境变量、时间字段、用户字段和命令字段,不必完整模拟 cron 调度器。

关键知识点:

  • 空行和 # 注释要跳过。
  • SHELL=PATH=MAILTO= 是环境变量,不是任务。
  • /etc/crontab/etc/cron.d/* 一般是“时间字段 + 用户 + 命令”。
  • 用户 crontab 一般是“时间字段 + 命令”。

Go 落地思路:

  • 解析结果保留原始行号,便于客户复盘。
  • 识别失败的行不要丢弃,可以作为低置信度原始证据。
  • 先按空白切分提取前 5 个时间字段,复杂表达式保留原样。
go
func cronCommand(fields []string, hasUser bool) string {
	start := 5
	if hasUser {
		start = 6
	}
	if len(fields) <= start {
		return ""
	}
	return strings.Join(fields[start:], " ")
}

5. 如何降低 cron 持久化检测误报?

简洁答案:把命令、用户、路径、资产角色、发布来源、历史基线和维护窗口放在一起判断,不要看到新增任务就报警。

常见误报:

  • 备份、日志轮转、监控探针和资产管理脚本。
  • 运维平台批量下发的定时巡检任务。
  • 业务为了清理缓存或报表生成配置的周期任务。
  • 安全软件自身的巡检或升级任务。

Go 落地思路:

  • 首次上线建立基线,只对后续新增、修改和异常频率提高风险。
  • 白名单必须带作用域,例如固定路径、固定 hash、固定用户和过期时间。
  • 被白名单压制的命中仍要计数,避免白名单过宽遮蔽真实攻击。

6. 如何把定时任务和攻击链关联起来?

简洁答案:定时任务说明“计划执行什么”,进程、文件和网络事件说明“实际发生了什么”,两者按时间窗口和命令指纹关联。

关键知识点:

  • cron 执行时父进程通常是 croncrondanacron
  • wrapper 脚本可能继续拉起子进程,不能只看第一层命令。
  • 低频任务可能跨天触发,配置修改时间和首次执行时间都要保留。
  • PID 会复用,关联时要带进程启动时间和事件时间。

Go 落地思路:

  • 生成命令指纹,例如规范化后的命令、脚本路径和 hash。
  • 关联字段包含 task_pathline_nocommand_hashprocess_tree
  • 告警展示从配置落地到进程执行再到网络外连的证据链。

7. at 一次性任务怎么检测?

简洁答案:at 任务适合延迟触发,检测重点是队列文件、执行用户、计划时间和任务内容摘要。

关键知识点:

  • at 队列通常位于 /var/spool/at 或发行版对应目录。
  • at 文件格式和权限依赖发行版,不同系统不能硬编码一种解析方式。
  • 攻击者可能用 at 延迟清理痕迹或延迟下载后门。

Go 落地思路:

  • 优先采集文件元信息、任务 owner、mtime、计划时间和内容摘要。
  • 解析失败时保留 hash 与原始大小,不阻塞其他采集。
  • 把 at 任务创建和异常登录、Web RCE、提权事件按时间窗口关联。

8. 客户反馈 cron 告警误报,怎么排查?

简洁答案:先确认任务来源和变更时间,再看命中原因、执行用户、脚本 hash、基线差异和相关进程行为。

排查顺序:

  1. 确认任务路径、原始行号、执行用户和修改时间。
  2. 查看命令是否来自可信发布系统、包管理器或运维账号。
  3. 对脚本路径补充 hash、属主、权限和最近变更记录。
  4. 关联该任务触发后的进程树和网络连接。
  5. 检查白名单是否过窄或过宽,并记录规则版本。

Go 落地思路:

  • 每条告警带 rule_idrule_versionrisk_reasons 和原始证据摘要。
  • Agent 输出扫描错误计数,例如权限拒绝、文件过大、解析失败。
  • 排障包只导出必要字段,避免上传完整脚本内容和敏感环境变量。

学习要点

方向要掌握的内容
Linux 原理cron、at、anacron、用户 crontab、spool 目录
检测工程配置落地检测、命令特征、攻击链关联、基线降噪
Go 实现filepath.WalkDir、逐行解析、文件元信息、hash 摘要、错误计数
客户排障任务来源、维护窗口、白名单作用域、规则版本、证据复盘

小练习

  1. 设计一个 ScheduledTaskFinding 结构体,字段至少包含任务路径、行号、执行用户、调度表达式、命令、风险原因和证据摘要。
  2. 写一个函数解析 /etc/cron.d 风格任务行,返回时间字段、用户和命令;空行、注释和环境变量要跳过。
  3. 设计一条规则:Web RCE 写入脚本后新增 cron 每 5 分钟执行,并在执行后外连公网 IP。列出至少 6 个证据字段。
  4. 复盘一个误报场景:运维平台下发合法巡检 cron,如何降噪但保留审计记录?
最近更新