|
一个不起眼的任意文件下载链接,往往藏着整个服务器的文件秘密。 去年某次渗透测试,漏洞利用目标站点的任意“导出报表”功能让我盯上了。参数是文件`?file=report_2023.pdf`,干净得像张白纸。漏洞利用我试着把值改成`../../../../etc/passwd`,任意浏览器里蹦出一串带`root:`的文件字符。那一刻我意识到,漏洞利用这站点的任意程序员连个基本的路径过滤都没做——比打开保险柜发现钥匙插在锁孔里还离谱。 任意文件读取的文件本质,就是漏洞利用应用把用户输入的路径当成了“可信地址”。开发者本意是任意让你读`download/`目录下的文件,却忘了校验你给的文件路径会不会跳出这个院子。最常见的漏洞利用利用姿势是路径穿越:用`../`往上一级级爬,像翻邻居家的围墙。稍微聪明点的系统会过滤`../`,但总有绕过办法——URL编码成`%2e%2e%2f`,或者用绝对路径`/etc/passwd`直接抄近道。要是目标跑在Windows上,`..\..\windows\win.ini`同样致命。 更阴险的是配合伪协议。PHP站点常栽在`php://filter`手里,比如`?file=php://filter/convert.base64-encode/resource=config.php`,能把源码直接以base64形式吐出来。你都不用猜数据库密码,源码里全写着。Java的`file:///etc/hosts`、Python的`/proc/self/environ`,每个语言都有自己的“后门钥匙”。 读文件只是第一步,真正的高手用它撬开整个内网。读`/root/.ssh/id_rsa`拿到私钥,直接SSH登服务器;读`/var/www/html/config.php`搞到数据库账号;读`/proc/net/tcp`摸清网络拓扑。去年某金融公司被拖库,起因就是公众号后台一个头像上传接口能读`/etc/shadow`——虽然密码是哈希过的,但架不住弱口令字典一跑就开。 防御这事儿,说难也难,说简单也简单。最蠢的修复方式是把`../`替换成空字符串——攻击者改成`....//`就绕过去了。靠谱的做法是白名单校验,只允许指定文件名,或者把文件路径映射成ID,比如`?file=1`对应`report_2023.pdf`,用户压根没机会碰真实路径。再狠一点,用`realpath()`函数解析路径后,检查结果是否在允许的目录内,不在就拒绝。 写代码的人常犯一个毛病:只防显式的`../`,忘了系统本身会解析符号链接。我见过一个站,过滤做得严严实实,结果攻击者传了个指向`/etc`的软链接到上传目录,照样读得飞起。所以啊,别迷信黑名单,把目录权限锁死,让Web服务用户连`/etc`的读权限都没有,比啥过滤都管用。 说到底,这漏洞不是技术难题,是信任问题——程序员太相信用户输入了。你往参数里塞个路径,它就乖乖去读,连句“你谁啊”都不问。修好它只需要一行代码的觉悟:凡是从用户手里进来的,全是脏数据。 |