/etc/ld.so.preload 被篡改的 ldd / LD_PRELOAD 环境变量排查

2次阅读

确认 /etc/ld.so.preload 是否被恶意写入最直接方式是 cat 查看内容,非空即被篡改;即使为空也需检查权限(应为 root:root 且 ≤644),宽松权限或非 root 属主表明系统已被渗透。

/etc/ld.so.preload 被篡改的 ldd / LD_PRELOAD 环境变量排查

怎么确认 /etc/ld.so.preload 是否被恶意写入

直接查看文件内容是最快速的判断方式:cat /etc/ld.so.preload。如果输出非空(比如出现类似 /tmp/.x.so/lib/libhook.so 的路径),基本可判定已被篡改;该文件本应为空或根本不存在。注意:即使文件存在但内容为空,也要检查其权限(应为 root:root 且权限 ≤ 644),若权限宽松(如 666)或属主非 root,说明系统已被渗透。

ldd 输出里为什么看不到 LD_PRELOAD 加载的库

ldd 是静态分析工具,它只读取 ELF 的 DT_NEEDED 段,不触发运行时动态链接器逻辑,因此完全无视 LD_PRELOAD/etc/ld.so.preload。想验证预加载是否生效,得用真实执行 + straceldd -v 配合环境变量测试:

  • 临时清空预加载:LD_PRELOAD= ldd /bin/ls —— 确认 baseline
  • 强制触发预加载:LD_PRELOAD="/tmp/mal.so" /bin/ls 2>/dev/NULL || true,再用 strace -e trace=openat,openat64 -f LD_PRELOAD="/tmp/mal.so" /bin/ls 2>&1 | grep mal 观察是否 open 成功
  • ldd -v 仍不会显示,别指望它

排查时容易忽略的绕过点:setuid 程序会忽略 LD_PRELOAD

这是 glibc 的安全机制:当进程有效 UID ≠ 实际 UID(即 setuid 程序,如 /usr/bin/passwd)时,动态链接器会自动丢弃 LD_PRELOAD/etc/ld.so.preload。所以即使你看到 LD_PRELOAD 被设了,对这类程序也无效——但攻击者可能正利用这点反向排查:如果某个后门只在普通用户进程生效、在 sudo 下失效,反而暴露了它依赖预加载机制。

验证方法:strace -e trace=openat -f /usr/bin/passwd 2>&1 | grep '.so' 不会命中预加载路径;而 strace -e trace=openat -f bash -c 'LD_PRELOAD=/tmp/x.so /bin/ls' 2>&1 会。

如何安全地清理并加固 /etc/ld.so.preload

清理本身很简单:sudo truncate -s 0 /etc/ld.so.preloadsudo rm /etc/ld.so.preload。但关键在后续加固:

  • 检查文件是否存在且为空:test ! -s /etc/ld.so.preload || echo "alert"
  • 禁止写入(推荐):sudo chown root:root /etc/ld.so.preload && sudo chmod 644 /etc/ld.so.preload && sudo chattr +i /etc/ld.so.preload+i 防止任何修改,包括 root)
  • 若必须保留该文件(极少见),确保路径指向的 so 文件存在、属主为 root、无 world-writable 权限
  • 监控变更:auditctl -w /etc/ld.so.preload -p wa -k ld_preload_watch,然后用 ausearch -k ld_preload_watch 查日志

真正难的是发现谁写的——/etc/ld.so.preload 被改,往往意味着攻击者已获得 root 权限,此时更该查 bash_historyauth.logsystemctl list-timers --all 里的可疑定时任务,而不是只盯着这个文件。

text=ZqhQzanResources