用stat可直接查看文件inode号、设备号及atime/mtime/ctime三个时间戳,其中ctime反映元数据变更,是检测异常改动的关键依据;单看inode号无法判断文件是否被替换,需结合(st_dev, st_ino)二元组与时间戳综合分析。

stat 怎么查文件的 inode 和时间戳
直接用 stat 查单个文件,就能拿到完整的 inode 编号、设备号、三个关键时间(atime/mtime/ctime)和大小。这些字段组合起来,是判断文件是否被异常改动的核心依据。
比如执行 stat /etc/passwd,输出里 Inode: 后面的数字就是它的 inode 号,Change: 行对应的是 ctime——只要权限、属主、扩展属性等元数据变了,这个时间就更新,哪怕内容没动。攻击者改完属主或加了 setuid,ctime 一定跳变,但 mtime 可能纹丝不动。
-
mtime异常滞后于ctime:说明文件内容没改,但权限/属主被动过,常见于提权后隐藏痕迹 -
atime突然频繁更新:可能是恶意脚本在批量读取配置或密钥文件 - 同一目录下多个文件
ctime在秒级内集中变更:大概率是自动化工具(如 Ansible、restorecon)批量操作,也可能是入侵者统一清理日志前的预处理
为什么不能只看 inode 号来判断文件是否被替换
inode 号本身不反映“变动”,它只是文件在该文件系统内的固定编号。一个文件被删再新建同名文件,新文件会拿到**全新 inode**;但如果只是 chown 或 chmod,inode 号完全不变——所以单看 inode 是否“相同”毫无意义。
真正要盯的是 (st_dev, st_ino) 这个二元组是否稳定,再叠加时间戳变化。比如你发现 /etc/shadow 的 st_ino 没变,但 ctime 比上次巡检快了 2 小时,就得立刻查 auditctl -w /etc/shadow -p wa 的审计日志,而不是怀疑文件被替换了。
- 跨挂载点(如
/home和/mnt/usb)的 inode 号重复是正常现象,st_dev才区分设备 - NFS 挂载时
st_dev常被映射成伪设备号,此时仅靠stat无法 100% 确认文件身份,需结合服务端日志 - ext4 下 inode 号重用有延迟(通常要等几小时甚至重启后才复用),短时间内看到相同 inode 出现在不同路径,基本可断定是硬链接,不是覆盖
用 find + stat 批量扫描敏感路径并筛选异常 ctime
想快速扫一遍 /etc 下所有配置文件,找出最近 1 小时内被改过权限或属主的,别写循环,用 find 配合 -cmin 和 -exec stat 一行搞定:
find /etc -type f \( -name "*.conf" -o -name "*.yaml" -o -name "sshd_config" \) -cmin -60 -exec stat -c "%n | %Z | %U:%G | %a" {} \;
这条命令会列出文件名、ctime 时间戳(秒级)、当前属主/属组、八进制权限。重点看 %Z 是否集中在某个时间点,以及 %U:%G 是否变成 root:root 以外的值——很多后门会悄悄把自身配置文件属主改成普通用户来绕过 root-only 检查。
- 避免用
-mtime替代-cmin:mtime只管内容修改,漏掉 chmod/chown 类操作 -
-cmin -60是精确到分钟的硬过滤,比stat后用awk算时间差更可靠,不受时区或夏令时干扰 - 如果目标路径含大量子目录(如
/var/log),加-maxdepth 2控制深度,否则可能卡在滚动日志里
stat 输出怎么跟 auditd 日志对上号
当你用 stat 发现某个文件 ctime 异常,下一步必须关联到具体是谁、什么进程干的。这时得靠 auditd 的 ausearch,但注意字段对齐:
stat 输出的 Change: 时间是人类可读格式(如 2026-04-20 15:22:03.123456789 +0800),而 ausearch -ts 要求 ISO 8601 格式且不含纳秒。正确做法是先用 stat -c "%z" /path 拿到带时区的 UTC 时间字符串,再用 date -d 截断到秒:
ctime_sec=$(stat -c "%z" /etc/hosts | cut -d' ' -f1,2); ausearch -ts "$ctime_sec" -k file_owner_change
这里 %z 输出的是 UTC 时间(stat -c "%Z" 是 Unix 时间戳,更稳妥),cut 去掉纳秒部分,确保能命中 ausearch 的索引。
- audit 规则必须用
-p wa(write + attribute),只写-p w会漏掉 chown/chmod -
ausearch默认查最近 24 小时,如果异常发生在更早时间,得加-ts 2026-04-19 00:00:00显式指定起始时间 - 若没开 auditd,
stat就只剩推测价值——它告诉你“变了”,但永远答不上“谁变的”











