FreeBSD文件完整性检查
网站部署或配置调整完成后,管理员通常希望知道哪些文件发生了变化。只比较文件大小容易漏掉等长修改,逐个打开文件又不方便。FreeBSD中的mtree可以记录指定目录的文件属性和内容摘要,再将当前状态与保存的基线进行比较。
以下示例先在独立测试目录中完成验证,检查过程只报告差异,不自动修复权限,也不删除多出来的文件。
一、确认环境与检查范围
以下操作以FreeBSD 15.1为例。
freebsd-version
command -v mtree
进入root权限的sh环境。
su -
/bin/sh
后续命令使用Shell变量保存路径,请在同一个Shell会话中依次执行。如果关闭了终端,必须先重新设置对应变量,不能直接从中间复制涉及文件移动的命令。
mtree只能检查基线中记录的项目。本文会比较文件类型、所有者、权限、大小、符号链接目标及SHA-256摘要,不将时间戳或ACL纳入这份示例基线。
二、创建独立测试目录
设置较严格的默认文件权限,并创建两个随机命名的目录。
umask 077
demo_dir=$(mktemp -d /root/mtree-demo.XXXXXX)
baseline_dir=$(mktemp -d /root/mtree-baseline.XXXXXX)
printf 'Test directory: %s\n' "$demo_dir"
printf 'Baseline directory: %s\n' "$baseline_dir"
记下输出路径。
其中,demo_dir保存被检查的文件,baseline_dir保存基线和报告,两者分开,避免检查结果本身反复造成目录变化。
创建示例文件。
mkdir -p "$demo_dir/conf" "$demo_dir/cache" "$demo_dir/logs"
printf '%s\n' 'mode=production' \
> "$demo_dir/conf/app.conf"
printf '%s\n' '<h1>Home</h1>' \
> "$demo_dir/index.html"
printf '%s\n' '<h1>About</h1>' \
> "$demo_dir/about.html"
chmod 644 \
"$demo_dir/conf/app.conf" \
"$demo_dir/index.html" \
"$demo_dir/about.html"
这些文件仅用于验证,不包含真实业务配置或密钥。
三、设置排除规则
缓存和日志会正常变化,可以根据业务需要将它们排除。本例建立一个简单的排除文件。
printf '%s\n' 'cache' 'logs' \
> "$baseline_dir/exclude.txt"
不带斜杠的规则按名称匹配,因此这两条规则也会匹配目录树中其他层级的同名条目。实际使用时,应确认排除范围,避免把需要保护的业务文件一并排除。
生成基线和后续检查时,要使用同一份排除规则。
四、生成目录基线
执行以下命令。
mtree -c -P \
-p "$demo_dir" \
-X "$baseline_dir/exclude.txt" \
-k type,uid,gid,mode,size,link,sha256digest \
> "$baseline_dir/site.mtree"
create_status=$?
printf 'Create exit status: %s\n' "$create_status"
只有退出状态为0,才继续使用这份基线。出现错误时,应先处理权限、文件读取或命令参数问题,不能将可能不完整的输出当成有效基线。
几个主要参数的作用如下。
-c生成目录规格清单。-p指定检查的根目录。-X读取排除规则。-k指定记录的属性。-P不跟随符号链接,比较链接本身。
sha256digest用于记录普通文件的SHA-256摘要,link用于记录符号链接指向的位置。它们检查的对象不同,不能互相替代。
查看基线开头的内容。
head -n 30 "$baseline_dir/site.mtree"
mtree的规格文件可能使用/set设置后续条目的公共属性,因此并不是每个文件都重复列出所有字段。
五、验证未变化时的结果
使用刚才的基线进行比较。
mtree -P \
-p "$demo_dir" \
-f "$baseline_dir/site.mtree" \
-X "$baseline_dir/exclude.txt"
check_status=$?
printf 'Check exit status: %s\n' "$check_status"
在文件未发生变化、检查正常完成的情况下,通常没有差异输出,退出状态为0。
mtree的退出状态需要分别处理。
0表示检查正常完成,目录与规格匹配。1表示发生了读取、解析等执行错误。2表示发现目录状态与规格不一致。
不要把所有非零状态都归为“文件被修改”,执行失败与发现差异是两种情况。
六、验证排除规则
向缓存和日志目录写入内容。
printf '%s\n' 'temporary cache data' \
> "$demo_dir/cache/item.tmp"
printf '%s\n' 'application log entry' \
> "$demo_dir/logs/app.log"
再次运行上一节的比较命令。
如果排除规则生效,这两个动态目录中的文件不应产生新增文件差异。正式使用前,建议通过这样的测试确认规则实际覆盖了哪些路径。
七、模拟需要识别的文件变化
以下操作只针对本例创建的测试目录。
先修改配置内容。
printf '%s\n' 'mode=staging' \
> "$demo_dir/conf/app.conf"
再修改首页文件权限。
chmod 600 "$demo_dir/index.html"
新增一个文件。
printf '%s\n' 'unexpected file' \
> "$demo_dir/extra.txt"
最后,将测试文件移到基线目录,模拟文件缺失,不直接删除它。
mv "$demo_dir/about.html" \
"$baseline_dir/about.html.saved"
现在执行检查并保存报告。
mtree -P \
-p "$demo_dir" \
-f "$baseline_dir/site.mtree" \
-X "$baseline_dir/exclude.txt" \
> "$baseline_dir/check-after.txt" 2>&1
check_status=$?
cat "$baseline_dir/check-after.txt"
printf 'Check exit status: %s\n' "$check_status"
在这些操作均正常完成的情况下,报告应指出以下差异。
conf/app.conf的内容摘要发生变化,也可能同时报告大小变化。index.html的权限与基线不同。extra.txt是基线中不存在的新增文件。about.html在当前目录中缺失。
本例没有使用忽略新增文件的-e选项,因此新增文件也会进入检查结果。
八、保护基线与排除规则
基线如果能够被随意修改,检查结果就失去了可靠依据。排除文件同样需要保护,否则扩大排除范围也可能让异常变化不再被报告。
可以记录两份文件的SHA-256值。
sha256 \
"$baseline_dir/site.mtree" \
"$baseline_dir/exclude.txt" \
> "$baseline_dir/baseline.sha256"
这份摘要记录有助于核对文件,但如果攻击者能够同时修改基线和摘要文件,仅将它们保存在同一台服务器上并不足够。
正式使用时,应保留可信的独立副本,并限制修改权限。基线包含文件路径和属性信息,也不应放到可被网站公开访问的目录中。
九、如何应用到真实目录
完成测试后,可以把-p参数替换成需要检查的配置目录或静态网站目录,并重新设计排除规则。
生成正式基线前,应先确认当前文件处于可信状态。不要在尚未查清异常时,直接把现状保存为“正常基线”。
还需要注意以下事项。
- 尽量在文件状态稳定时生成和检查,避免部署过程造成临时差异。
- 对日志、缓存及其他正常变化的内容设置明确的检查策略。
- SHA-256检查需要读取文件内容,大目录会产生磁盘I/O,应选择合适的执行时间。
- 本例不跟随符号链接,链接指向目录之外的内容不属于这次检查范围。
- 只更新经过确认的基线,保留旧版本和变更记录。
如果需要进一步查明操作事件,可以结合站内的FreeBSD安全审计教程。mtree负责比较状态差异,auditd用于记录选定的审计事件,两者用途不同。
十、常见问题
1. 出现差异是否就代表服务器被入侵
不代表。正常部署、管理员修改配置以及应用生成文件,都可能产生差异。应结合发布时间、操作记录和文件内容判断。
2. mtree会自动恢复被修改的文件吗
本文命令不会。mtree的-u、-U等选项可以修改部分属性,-r还会删除规格之外的文件,这些选项不应直接加入只读巡检命令。
3. 有了基线是否可以不做备份
不可以。摘要和属性清单无法代替文件内容备份,也不能恢复丢失的业务数据。
广告合作
QQ群号:4114653
- 本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。邮箱:2942802716#qq.com(#改为@)。
- 本站原创内容未经允许不得转载,转载请注明出处“站长百科”和原文地址。