任意文件下载漏洞修复方案
一个真实的任意案例比任何理论都更有说服力。去年某电商平台的文件安全测试中,测试人员仅仅修改了下载接口中一个文件名的下载修复参数,就成功下载到了服务器上的漏洞 任意文件下载漏洞的文件本质,是下载修复服务器把用户可控的参数当成了文件路径的一部分。常见的漏洞有两种触发方式,一种是任意 修复方案要分三层来做。第一层是白名单校验,这层要做死。后端维护一个允许下载的文件ID到真实路径的映射表,用户只能传ID,不能传路径。如果业务上确实需要传文件名,那就用正则严格限制字符集,只允许字母数字下划线和点,同时禁止任何形式的编码绕过—— 第二层是路径规范化。即使你做了白名单,也要防住那些通过其他渠道进来的拼接操作。用Java的 第三层是系统层面的兜底。比如在Linux上用 还有个容易被忽略的点:响应头。下载文件时, 最后说个我自己的判断。很多修复方案只盯着代码层,但真正有效的防御是架构层面的——把用户可控的文件名彻底从业务逻辑中剥离。比如上传文件时,用UUID重命名存储,数据库里只存UUID,下载时拿UUID去查存储路径。这样就算攻击者猜破了天,也拿不到真实路径。这比任何过滤函数都可靠,因为根子上就没有路径拼接这回事。代码审查时,看到 /etc/passwd 文件。这不是任意黑产高手的高深技巧,而是文件新手都能复现的路径穿越操作。那个漏洞的下载修复根源,就是漏洞开发者直接拼接了用户输入的文件名,没有做任何过滤。任意download?file= 这种直接指定路径的,另一种是文件 read?name=xxx 这种先查数据库再拼路径的。前者好理解,下载修复后者往往藏得更深——你以为查出来的是合法文件名,但数据库里存的数据可能早就被污染了。%2e、..%2f、双重URL编码这些都要测一遍。有个取巧的办法是,对参数先做一次URL解码,再对解码后的值做二次校验,能挡住大部分基础攻击。Paths.get(base, userInput).normalize() 或者Python的 os.path.realpath(),把最终解析出来的绝对路径拿过来,检查它是否以你预设的下载目录开头。这一步不能省,因为有些框架内部会自动拼接路径,你根本不知道它拼在哪。我见过一个案例,开发自以为做了过滤,结果框架在拼接时自动把 .. 给解析了,绕过了所有检查。chroot 或者容器隔离,把下载服务限制在一个独立的目录树里。Windows上可以给IIS配置请求过滤,拒绝包含 .. 的URL。这些手段不是给你偷懒的借口,而是当上面两层被绕过时,还能把伤害控制在最小范围。别忘了给下载目录设置只读权限,同时禁止符号链接——很多渗透测试就是靠软链接指向敏感文件得手的。Content-Disposition 的 filename 参数要固定写死,别用用户输入来拼。否则攻击者可能通过构造特殊文件名,触发响应头注入,那又是另一个漏洞了。另外,如果下载的是静态资源,尽量走CDN或对象存储,把下载逻辑从应用服务器上剥离开,连漏洞面都没有了。file、path、name 这些参数直接出现在文件操作函数里,就该亮红灯。
-
上一篇
-
下一篇
- 最近发表
- 随机阅读
- 搜索
-
- 友情链接
-