去年秋天,列目录漏一个做跨境电商的洞修朋友给我发来一个链接。点开一看,列目录漏满屏都是洞修服务器上的文件列表——日志、备份、列目录漏甚至数据库配置。洞修他问我这算不算大事。列目录漏我说,洞修这就像你家大门没锁,列目录漏还把钥匙插在锁孔上,洞修顺便贴了张纸条写着“欢迎光临”。列目录漏
列目录漏洞,洞修说白了就是列目录漏Web服务器把某个目录下的所有文件名、大小、洞修修改时间,列目录漏甚至子目录结构,赤裸裸地列在浏览器里。你访问一个URL,本该看到网页,结果看到的是Apache或Nginx默认的索引页面。这不是什么高深的技术漏洞,但它的杀伤力被严重低估了。
我见过最离谱的一个案例,某企业的/backup/目录直接暴露在公网。里面躺着三个.sql文件,每个都超过2GB。数据库结构、用户表、订单记录,全在里面。攻击者甚至不需要任何渗透工具,浏览器打开,右键另存为,完事。整个入侵过程不超过两分钟。企业后来复盘,说开发人员图省事,把备份脚本的输出路径设在了Web根目录下,而Nginx的autoindex默认是开的。
这暴露了一个问题:很多人把“能访问”和“该访问”混为一谈。服务器配置里,autoindex on;这行指令写起来轻松,后果却可能是灾难性的。Apache那边,Options Indexes也是同样的道理。默认配置往往为了“方便调试”而牺牲了安全性,上线时却没人记得改回来。
修复这件事,其实不复杂,但需要你真正理解请求是怎么走的。最直接的办法,在Nginx里把autoindex off;写进http、server或location块。如果某个目录确实需要列出来,单独给它开。Apache的话,把Options Indexes改成Options -Indexes。就这么一行,能挡住绝大多数扫描器。
但光关掉索引还不够。我见过一些站点,虽然关了目录列表,但/uploads/下面直接放了.zip和.tar.gz,文件名又特别有规律,比如backup_20231015.zip。攻击者不需要目录列表,用字典跑一遍就猜到了。所以,敏感文件别往Web目录里扔。备份、日志、配置文件,统统挪到Web根目录之外。如果非放不可,用location规则拒绝访问,或者加个随机前缀。
还有一个容易忽略的点:错误页面的信息泄露。有些服务器在返回403时,会附带“目录索引被禁止”之类的提示,反而告诉攻击者“这里有个目录”。更好的做法是直接返回404,让扫描器以为路径不存在。我自己的服务器上,所有被拒绝的请求都统一返回一个空白404页,不解释、不提示。
说回那个跨境电商的朋友。我让他查了Nginx配置,果然,autoindex on;明晃晃地写在location /static/里。开发当初为了调试静态资源方便,上线后忘了删。更糟的是,/static/下面有个config/子目录,里面放着支付网关的密钥文件。我们关掉索引、移走密钥、加了条deny all;规则,前后不到十分钟。他后来跟我说,那十分钟比过去一年做的安全加固都值。
列目录漏洞的修复,本质上不是技术问题,是习惯问题。开发时随手开的调试选项,上线前有没有人复查?部署脚本里有没有硬编码的路径?运维和开发之间的交接清单上,有没有“检查目录索引”这一项?这些问题的答案,往往比漏洞本身更值得琢磨。
我自己的做法是,每次上线新服务,先用curl -I跑一遍常见路径,看看返回什么。再拿dirsearch扫一下,确认没有意外的200响应。花不了五分钟,但能睡个安稳觉。毕竟,你永远不知道下一个被列出来的目录里,藏着什么不该见光的东西。