当前位置:首页 > 知识

目录遍历漏洞

一个下午,目录我盯着Burp Suite的遍历响应窗口,心跳漏了一拍。漏洞目标站点的目录`download.php?file=`参数后面,老老实实地跟着`../../../../etc/passwd`。遍历服务器没有过滤,漏洞没有WAF拦截,目录直接吐出了root用户的遍历信息。

这不是漏洞什么高深的攻击。目录遍历漏洞,目录老古董了,遍历比我的漏洞职业生涯还老。但每次看到它,目录我都觉得像在博物馆里撞见一把没上锁的遍历保险柜。

漏洞的漏洞原理简单得近乎粗暴——应用程序在处理文件路径时,没有对用户的输入进行有效过滤。你给它一个相对路径,它就老老实实地去拼接。`../`往上跳一级,`..\\`在Windows下同样有效。攻击者像在迷宫里走楼梯,一层一层往上,总能摸到不该进的门。

真实世界里,这个漏洞往往藏在文件下载、图片预览、导出报表这类功能里。开发者的本意是让用户访问某个固定目录下的文件,但代码写成了`file_get_contents($_GET['path'])`——直接把参数当路径用了。这种代码我见过太多次,每次都想问:写的时候到底在想什么?

有些案例让人哭笑不得。某个政府网站,把PDF文件放在`/uploads/`目录,下载接口却写成了`/download?file=../../uploads/xxx.pdf`。攻击者只要把`uploads`换成`etc`,就能读到系统配置文件。开发者的本意是防止用户直接访问文件,结果反而把整个服务器的目录结构暴露了。

更麻烦的是,目录遍历往往只是第一步。拿到`/etc/passwd`不算什么大事——现在大多数系统密码都在`/etc/shadow`里,权限锁得死死的。但如果你运气好,碰到一个把数据库备份放在`/backup/`目录下的服务器,再配合一个没有做权限控制的遍历点,那整库的用户名、密码哈希、甚至明文手机号都一览无余。我见过一个电商站,备份文件就躺在`/var/www/html/backup/`里,文件名带日期,遍历一下就能枚举出来。

防御手段其实不复杂,但总有人懒得做。最有效的办法是白名单校验——直接判断文件名是否在允许的列表里,而不是去过滤`../`。黑名单永远有疏漏,编码绕过、大小写绕过、双写绕过,每种绕过方式都能写一篇论文。另一个办法是把文件访问映射成ID,比如`download.php?id=5`,后端去数据库查这个ID对应的真实路径,用户永远碰不到实际的文件路径。

有一次我给客户做渗透测试,发现他们的文件服务器有个遍历点,能读到`C:\Windows\system32\drivers\etc\hosts`。我上报时写了句“影响较低”,客户也回了句“知道了”。三个月后复查,漏洞还在。我琢磨了一下,也许在他们眼里,只要不泄露用户数据,系统文件读一读也无所谓。这种心态挺危险的——攻击者拿到系统文件名和路径结构,下一步就是配合其他漏洞找写文件的点了。

说到底,目录遍历是个懒惰的漏洞。它不需要精妙的构思,不需要零日利用,只需要开发者少写一行校验代码。在云原生、容器化大行其道的今天,这种老漏洞依然活跃在各类资产里。我甚至在一个K8s集群的内网服务上见过它,容器里跑着Nginx,配置了个alias指向`/`,直接暴露了整个根文件系统。容器没做只读根文件系统,攻击者可以往`/tmp`里扔个webshell——当然,前提是他得先找到能执行代码的入口。

修复方案早就写烂了,但每次看到这类漏洞,我都觉得技术从来不是瓶颈,人的惰性才是。写代码的瞬间多问一句“这个参数能不能被用户控制”,比事后打补丁省事得多。可惜,大部分时候,这句话没人问。

分享到: