我花了三个小时逆向一个开源VPN客户端,模拟最后发现漏洞根本不在加密协议里,可信而在它读取配置文件的任目路径上。这个路径允许用户写入一个叫 .hidden 的录漏目录,而系统管理员默认信任了这个目录——因为名字里带点,洞利看起来就像系统自动生成的模拟。这就是可信典型的可信任目录漏洞利用:攻击者不需要攻破你的密码,只需要找到一个你“想当然”会安全的任目地方。
具体点说,录漏很多程序会硬编码一些目录来存放临时文件或插件,洞利比如 /var/tmp/app 或者用户主目录下的模拟 .config。开发者觉得这些位置“只有自己人能用”,可信于是任目省略了权限校验。但现实是录漏,Linux 下 /tmp 和 /var/tmp 是洞利全世界可写的,而某些安装包会错误地把敏感操作指向这些共享空间。我见过一个真实案例:某网盘客户端把下载链接的签名缓存写在 /tmp/cloud_cache,结果任何本地用户都能往这个目录里塞伪造的签名文件,让客户端误以为某个恶意文件是官方更新。
更阴险的是利用符号链接。攻击者先删除目标目录,然后创建一个指向 /etc/passwd 的软链接,程序再往“信任目录”里写文件时,实际上就覆盖了系统关键文件。这招老套但有效,尤其当程序以 root 权限运行时。我测试过一个小型数据库软件,它启动时会在 /var/run/db 下创建 socket 文件,但没检查该目录是否已被劫持。我把这个目录替换成指向 /home/user/.ssh 的链接,重启服务后,socket 文件直接生成在 SSH 目录里,配合目录遍历就能读取私钥。
防御手段其实不复杂,但需要改掉“信任惯性”。第一,永远不要假设某个路径是安全的,除非你显式地创建它并设置 0700 权限。第二,检查目录是否存在前,先 lstat() 看它是不是符号链接,而不是用 access()。第三,使用 openat() 这类带目录文件描述符的 API,从根本上防止路径被中途替换。我见过太多代码只做了“存在性检查”,却忽略了 TOCTOU(时间-of-check-to-time-of-use)竞态——检查时目录正常,使用时已经被掉包。
最让我恼火的是那些号称“安全加固”的框架,内部却依然把用户可控路径拼进 system() 调用。上个月我审计一个物联网管理后台,它允许用户上传固件到 /opt/firmware,然后通过 shell 脚本去执行里面的校验程序。攻击者只需上传一个同名可执行文件,替换掉真正的校验器,整个刷机流程就变成后门安装流程。这已经不是技术漏洞,而是设计上的懒惰。
所以,下次你看到某个目录名特别“系统”或者“隐藏”,别急着信任。先想想:如果我是攻击者,我能往这里放什么?如果答案是不确定,那它就不该被信任。