引言
在我们之前的博客文章《Hiding in plain sight: Techniques and defenses against /proc filesystem manipulation in Linux》中,我们探讨了如何从取证分析工具中隐藏恶意进程的技术。取证分析师经常依赖Linux虚拟文件系统/proc来枚举进程、重建时间线并将活动归因于特定可执行文件。诸如ps、top和各种取证脚本等工具从/proc/<pid>/目录下的文件(包括cmdline和stat)中提取进程元数据。因此,这些文件的完整性对许多事件响应工作流程至关重要。
我们的研究表明,拥有特权访问权限的威胁行为者或某些类型的恶意代码可以操纵/proc视图,从而创建具有误导性的取证证据。通过修改这个内核接口,威胁行为者可以通过替换显示的命令行参数来混淆进程身份,并可以篡改诸如记录的进程启动时间等时间数据,从而破坏时间线分析。
关键发现
/proc/<pid>/cmdline可以被替换或编辑,以呈现任意命令字符串,从而使进程识别复杂化。/proc/<pid>/stat中的starttime字段可以被更改,导致时间线不一致,包括产生破坏事件关联的未来时间戳。- 由于篡改需要提升的权限或内核修改,因此成功的篡改是主机遭受严重入侵的强烈迹象。
- 孤立地依赖
/proc会增加取证分析出现假阴性(漏报)和归因错误的风险;必须通过与内核和远程遥测数据进行交叉验证。
目标读者
- 网络安全分析师
- 恶意软件与威胁情报专业人员
- 事件响应者
- 安全运营团队
技术详解
环境与目标
实验在Linux主机上进行,使用一个在交互式shell中运行的最小测试脚本(“规避”脚本)。目标有两个:
- 演示如何替换
/proc/<pid>/cmdline可以改变ps/top显示的命令字符串。 - 强调编辑
/proc/<pid>/stat中的starttime字段如何在转换为人类可读格式时产生时间不一致(包括“未来”)的进程启动时间。
测试过程:小型交互式脚本
目标进程是一个名为evasion的最小脚本:
|
|
启动脚本后,进程出现在进程列表中(来自ps aux的示例摘录):
|
|
克隆目标进程的/proc数据
我们创建一个工作区,并将实时/proc/<pid>字段复制到工作区:
|
|
复制后,工作区的内容为空,直到将证据文件放入其中。我们打算稍后将该文件夹用作绑定挂载的目标。
将克隆的数据通过绑定挂载覆盖到/proc/<pid>
通过将/tmp/evil绑定挂载到/proc/18316上,可以将用户态工具看到的进程的内核导出视图重定向到替换的文件:
|
|
绑定挂载后,ps aux不再报告原始的./evasion字符串,因为进程视图已被挂载的证据文件替换。例如,初始的ps aux显示了该进程,但在挂载工作区后,ps输出不再显示evasion,只出现grep进程。
将编辑后的证据文件放入已挂载的文件夹
接下来,将先前复制的文件写入已挂载的文件夹并进行编辑。以下是我们调查期间执行的命令示例:
|
|
此时,读取/proc/18316/cmdline和/proc/18316/stat的用户态工具将读取存储在/tmp/evil中的版本。evasion进程现在由那些被替换的证据文件支持。
演示:替换命令字符串
/tmp/evil中的cmdline文件被编辑为包含单个标记safeprocess:
|
|
经过此替换后,ps aux显示PID 18316的新命令字符串:
|
|
因此,通过替换/proc/18316/cmdline处暴露的cmdline内容,进程名称的实时显示从/usr/bin/bash ./evasion更改为safeprocess。这演示了当攻击者控制导出文件时,基于/proc的识别是多么容易被欺骗。
Stat证据文件:原始与解析
stat文件包含许多数字字段。在本实验中,捕获的进程stat行如下:
|
|
借助proc_pid_stat(5),我们可以将这些数字字段转换为更易理解的顺序:
| (1) pid %d | (8) tpgid %d | (15) stime %lu | (22) starttime %llu |
|---|---|---|---|
| (2) comm %s | (9) flags %u | (16) cutime %ld | (23) vsize %lu |
| (3) state %c | (10) minflt %lu | (17) cstime %ld | (24) rss %ld |
| (4) ppid %d | (11) cminflt %lu | (18) priority %ld | (25) rsslim %lu |
| (5) pgrp %d | (12) majflt %lu | (19) nice %ld | (26) startcode %lu [PT] |
| (6) session %d | (13) cmajflt %lu | (20) num_threads %ld | (27) endcode %lu [PT] |
| (7) tty_nr %d | (14) utime %lu | (21) itrealvalue %ld | (28) startstack %lu [PT] |
解释这些字段需要参考proc(5);特别是,字段(22)是starttime,即进程在系统启动后开始的时间,以时钟滴答数表示。
为了简化解释,实验使用了一个小型辅助程序procstat将数字字段转换为人类可读的形式。以下是示例输出:
|
|
procstat工具将starttime时钟滴答值转换为可读的时间戳和相对年龄(例如,698.43秒),这对时间线关联很有用。
将starttime转换为绝对时间
必须根据系统启动时间来解释starttime值。在本实验中,捕获的系统正常运行时间如下:
|
|
使用原始stat文件中存在的数字starttime值(48156368),报告显示该进程在观察点之前大约85秒启动(实验室中通过_SC_CLK_TCK将时钟滴答转换为秒数,并与正常运行时间进行比较计算得出)。然后,procstat工具报告start_time: 10.12 22:06 (698.43s),说明了原始stat数据是如何转换为人类可读的解释的。
篡改starttime以制造时间误导信息
为了说明时间线是如何被操纵的,将/tmp/evil/stat中的starttime字段从48156368编辑为98156368:
|
|
修改starttime并保持cmdline替换后,ps aux现在报告该PID的日历日期相对于实际系统时间而言是未来的。在我们的测试期间,系统日期/时间为:Sun Oct 12 10:24:07 PM +07 2025。更改starttime后,ps输出为PID 18316显示的进程开始日期为Oct18(即未来日期)。
这演示了编辑stat记录中的starttime数字字段如何导致实用程序显示误导性的日历时间戳——有效地将进程“移动”到未来并破坏时间线关联。
结论
/proc伪文件系统是进程自省的一个便利渠道,但在对抗性环境中并非不可变的证据存储。特权行为者可以操纵/proc条目以隐藏身份并篡改时间线重建所依赖的时间数据。有效的检测需要将/proc视为众多证据来源之一,并根据基于内核的遥测数据和远程不可变日志来验证进程事件。
检测与防御建议
- 监控挂载和卸载系统调用:使用诸如
auditd或eBPF等工具来检测可疑的挂载活动。 - 对异常的
/proc挂载发出警报:如果/proc/[pid]被挂载到tmpfs或任何外部文件系统,则生成警报。 - 交叉验证
/proc数据:将/proc条目与内核和远程遥测源(如auditd、EDR内核事件流、systemd日志时间戳和远程日志)进行比较,以维持可信的时间线。 - 限制特权访问:应用最小权限原则,强制执行RBAC(基于角色的访问控制),并仅允许加载经过签名或授权的内核模块。
- 实施不可变的审计日志转发:将关键审计日志转发到远程的、只写一次的存储中,以在主机被篡改的情况下保存证据。
- 启用内核完整性控制:在可能的情况下,启用安全启动、内核模块签名和主机证明以确保完整性。
- 增强取证分析工具:更新取证分析脚本,标记
/proc与独立遥测源之间的不一致之处,并默认将/proc条目视为“不可信”。
常见问题解答
Linux中的/proc文件系统是什么?
/proc文件系统是一个虚拟接口,提供关于运行中的进程和内核参数的详细实时信息。它被ps、top和取证脚本等系统工具广泛使用,以从/proc/<pid>/目录下的文件(包括cmdline和stat)中检索进程元数据。
为什么/proc在数字取证和事件响应中很重要?
在取证调查中,/proc是识别运行中进程、重建执行时间线以及将活动归因于特定可执行文件的基础来源。分析师依赖其提供的数据,以确定事件期间进程行为和系统状态的上下文。
攻击者如何操纵/proc数据?
拥有提升权限的攻击者可以更改/proc视图以隐藏或伪造信息。这可以通过替换/proc/<pid>/cmdline文件来显示任意命令字符串,从而有效地重命名或伪装恶意进程来实现。他们还可以编辑/proc/<pid>/stat文件以修改记录的进程启动时间,甚至将其设置为未来时间戳。这些更改通常通过将备用目录绑定挂载到原始的/proc路径上来实现,从而重定向用户态工具看到的内容。
/proc操纵对调查有什么影响?
操纵/proc会通过掩盖进程的真实身份或伪造其执行时间来误导取证工具和分析师。这种欺骗可能导致不正确的或误导性的取证时间线,导致分析师忽略恶意活动,并导致假阴性(漏报)或归因错误。
进行这种操纵需要什么级别的访问权限?
编辑/proc条目需要root或内核级权限。这意味着成功的操纵是系统遭受严重入侵的强烈迹象,因为普通用户无法修改/proc中内核导出的数据。
防御者如何检测/proc操纵?
检测需要监控异常的系统行为,并在多个来源间验证进程数据。系统管理员应使用auditd或eBPF等工具监控挂载和卸载系统调用,并在/proc/[pid]被挂载到像tmpfs这样的非标准文件系统时生成警报。在/proc数据和独立遥测源(如内核日志、审计记录、EDR事件和systemd日志时间戳)之间进行交叉验证,可以揭示表明篡改的不一致之处。