Skip to content

Go 主机安全面试:Linux fanotify 与 Web 后门落地检测

Web 后门落地检测看起来像“监控目录里有没有新增文件”,但面试里真正考的是:你能不能讲清楚 Linux 文件事件采集的能力边界,如何把文件变化、写入进程、Web 服务账号、脚本后缀、访问日志和后续执行串成一条可信证据链。

inotify 很轻,适合盯固定目录变化;fanotify 能覆盖更高层的文件访问通知,部分模式还能拿到文件描述符;audit/eBPF 更适合补“谁写的、谁执行的”。主机安全产品通常不会押宝单一来源,而是用最小成本组合出可解释告警。

岗位场景

text
Web 服务器
  -> 监听站点目录、上传目录、临时目录和 include/plugin 目录
  -> 捕获 create/write/rename/chmod/delete 等文件变化
  -> 标准化 path、inode、owner、mode、hash、writer process、web user
  -> 关联 HTTP 访问日志、Web RCE 进程链、脚本执行和外联
  -> 对发布系统、CI/CD、插件升级、日志轮转和正常上传做降噪

高频面试题

1. 为什么 Web 后门落地不能只靠定时扫描?

简洁答案:定时扫描能发现最终状态,但容易错过短生命周期文件、rename 过程和写入主体;实时事件能提供更完整的时间线。

关键知识点:

  • 攻击者可能先写临时文件,再 rename 成脚本后缀。
  • 后门可能落地后很快执行、删除或改权限。
  • 定时扫描适合作为兜底基线,事件采集适合补时间顺序。
  • 告警价值不只是“文件存在”,还包括“谁写入、何时写入、之后做了什么”。

Go 落地思路:

  • 固定 Web 根目录用 inotify/fanotify 做增量触发。
  • 定时快照保存 path + inode + size + mode + mtime + sha256,补漏和重启恢复。
  • 事件里保留 source 字段,区分来自实时监听还是快照 diff。

2. inotify 和 fanotify 在 HIDS 里怎么取舍?

简洁答案:inotify 部署简单,适合目录级变化通知;fanotify 更适合文件访问通知和挂载点级监控,但权限、内核版本和性能成本更敏感。

关键知识点:

  • inotify 关注目录和文件路径变化,事件里通常没有完整进程上下文。
  • fanotify 可以按 mount 或 filesystem 维度接收事件,部分事件能拿到 fd。
  • fanotify 权限事件用错会拖慢 IO,HIDS 默认应优先通知模式。
  • 两者都不是“万能归因工具”,进程主体通常要靠 audit/eBPF 或临近时间窗口关联。

Go 落地思路:

  • 小站点目录先用 inotify,覆盖多个挂载点或需要 fd 元数据时再考虑 fanotify。
  • 本地 Agent 只做轻量归一化和采样,复杂关联放到服务端。
  • 明确上报采集能力:watch_backend=inotify|fanotify|snapshot

3. 如何判断一个新增 PHP/JSP/ASP 文件是不是 WebShell?

简洁答案:不能只看后缀,要结合目录角色、文件内容特征、写入进程、账号、权限、访问日志和后续行为。

关键知识点:

  • 上传目录出现可执行脚本比静态资源目录更可疑。
  • evalassertsystemshell_execbase64_decode 是风险特征,但业务代码也可能使用。
  • WebShell 常伴随异常 HTTP 参数、短时间命令执行、反弹 shell 或内网探测。
  • 发布系统、插件市场、CMS 升级会产生大量合法脚本变更。

Go 落地思路:

  • 文件内容只做小窗口扫描,限制最大读取字节,避免拖垮 Agent。
  • 规则输出 reason code,例如 script_in_upload_dirrisky_php_apiweb_user_write
  • 对大文件、二进制文件和频繁变动目录做跳过或降采样。
go
func riskyScript(path string, data []byte) bool {
	ext := strings.ToLower(filepath.Ext(path))
	if ext != ".php" && ext != ".jsp" && ext != ".asp" && ext != ".aspx" {
		return false
	}
	s := strings.ToLower(string(data))
	return strings.Contains(s, "eval(") ||
		strings.Contains(s, "shell_exec") ||
		strings.Contains(s, "base64_decode")
}

4. 没有进程上下文时,怎样补“是谁写的”?

简洁答案:用近时间窗口把文件事件和进程事件、HTTP 日志、audit/eBPF 写入事件关联;没有强证据时要降低置信度。

关键知识点:

  • 文件事件只有路径变化时,不能硬说某个进程就是写入者。
  • Web RCE 常见链路是 nginx/apache/php-fpm/java 子进程写文件,再执行命令。
  • rename 会让最终路径和原始写入路径不同,要保留 inode 和临时路径。
  • PID 会复用,关联进程必须带启动时间。

Go 落地思路:

  • 维护短窗口 ring buffer,按 inode/path/time 关联 exec、open/write、HTTP 请求和网络事件。
  • 证据强度分层:audit/eBPF 写入主体 > fanotify fd 元数据 > Web 日志临近访问 > 纯路径变化。
  • 告警字段里写明 confidencemissing_evidence

5. 如何降低发布系统和正常上传造成的误报?

简洁答案:把业务基线纳入规则:发布窗口、发布账号、CI/CD 进程、包管理路径、允许后缀、目录角色和历史 hash 分布。

关键知识点:

  • 正常发布通常批量、稳定、可追溯,并来自固定账号或部署工具。
  • 攻击落地更常见于 Web 用户、临时目录、上传目录和非发布时段。
  • 允许名单不能只按路径放行,否则攻击者会利用上传目录。
  • 降噪要保留命中原因,方便客户调整策略。

Go 落地思路:

  • 配置站点目录角色:staticuploadtemplatepluginruntime
  • 对 CI/CD 进程和发布窗口降权,不直接静默。
  • 服务端按租户维护基线,Agent 不塞复杂策略。

6. fanotify 事件量太大时怎么做性能控制?

简洁答案:先缩小监控范围,再做事件合并、后缀过滤、限速、哈希延迟计算和采样;不要在 IO 热路径里做重内容分析。

关键知识点:

  • Web 缓存、日志、临时文件和上传大文件会制造大量事件。
  • 频繁计算全量 hash 会增加磁盘 IO。
  • 权限事件可能阻塞业务 IO,默认不要启用拦截模式。
  • 事件丢失和队列溢出必须显式暴露,否则检测结果不可解释。

Go 落地思路:

  • context.Context 控制 watcher 生命周期。
  • 对同一路径短时间多次写入做 debounce,稳定后再 hash。
  • 上报 dropped_eventsqueue_laghash_skipped_reason 等健康指标。

7. WebShell 落地后还要关联哪些后续行为?

简洁答案:重点关联脚本被访问、解释器执行命令、反弹 shell、下载二阶段载荷、提权和横向移动。

关键知识点:

  • 落地文件只是攻击链前半段,后续执行更能提升置信度。
  • 可疑进程包括 shbashcurlwgetpythonperlnc 等。
  • Web 服务账号发起外联、读取敏感文件或执行系统命令都很可疑。
  • 攻击链还原要保留时间顺序,不要只输出孤立 IOC。

Go 落地思路:

  • 用统一 entity_id 关联 file、process、network、http_request。
  • 告警摘要按时间线输出:文件写入 -> HTTP 访问 -> 命令执行 -> 外联。
  • 同一攻击链只生成一个主告警,避免每个子事件刷屏。

8. 面试里如何评价“用 fanotify 做实时 WebShell 检测”的方案?

简洁答案:方向可行,但不能把 fanotify 当成完整检测系统;它适合做文件事件入口,归因、降噪和攻击链关联还需要其他数据源。

关键知识点:

  • 采集源负责看见变化,检测系统负责解释变化。
  • 生产方案要考虑权限、内核版本、容器挂载、overlayfs、事件丢失和性能。
  • 对客户有价值的是可解释证据链,而不是单个 API 名称。
  • 最稳妥的架构是“实时事件 + 快照兜底 + 行为关联 + 策略降噪”。

Go 落地思路:

  • 先做最小可用模型:目录监听、快照兜底、风险后缀、轻量内容扫描。
  • 再按环境接入 audit/eBPF 补强写入主体和执行链路。
  • 保留采集状态和降级路径,避免某个 watcher 失败后静默漏报。

学习要点

模块要点
文件事件inotify、fanotify、rename、chmod、delete、队列溢出
Web 安全WebShell、上传目录、解释器、Web RCE、访问日志
Linux 原理inode、fd、权限、mount、overlayfs、PID 复用
Go 实现watcher 生命周期、debounce、hash 限流、事件归一化
检测工程证据强度、攻击链关联、误报治理、健康指标

小练习

  1. 设计一个 FileChangeEvent 结构体,至少包含路径、inode、事件类型、来源、hash 和置信度。
  2. 如果只拿到 inotify 事件,没有 audit/eBPF,你会如何表达“疑似 Web 用户写入”的不确定性?
  3. 为什么上传目录里出现 .php 比静态目录里出现 .jpg 风险更高?
  4. 写一个 debounce 策略:同一路径 3 秒内多次写入只计算一次 hash。
  5. 画出 WebShell 落地到反弹 shell 的 5 个关键事件。
  6. 给发布系统、CMS 插件升级和攻击落地各设计 2 个区分特征。

复盘题

  • fanotify 相比 inotify 的优势和代价是什么?
  • 为什么文件后缀、内容关键字和路径都不能单独作为恶意结论?
  • 如何把文件事件、HTTP 请求、进程执行和网络连接组织成一条告警时间线?
  • 如果事件队列溢出,Agent 应该如何上报和补偿?
最近更新