如题,最近在进行系统安全测试的时候,文件下载出了点问题,fortify扫描出了header manipulation漏洞。因为接手的是别人的代码,很疑惑他当时为什么要用控制响应头的方法去进行文件下载传输。
原来的代码大概是这样的
@RequestMapping("files/download",method=RequestMethod.GET)
public void download(@RequestParam String fileName){
FileInfo fileInfo = RedisUtil.get(RedisKeyConstants.FILE_PREKEY + fileName);
//业务逻辑处理
response.setHeader("Content-disposition","attachment;fileName=" + fileName);
....
}
在response.setHeader这一行一直报header manipulation
乍一看确实是没什么问题的,但怀着b了狗的心情,csdn上找了一番,都是让我去校验文件名。后来抄了个正则,校验了一下,然并卵,fortify并不知道你校验了。。。
万恶的测试,迟早有一天我要把你们全部砍死。。心里默默的yy了两句。
后来找了篇文章,看到了这个漏洞的共计原理,本质原因就是你使用了用户的入参给用户进行了响应。。那么问题来了,如果用户的入参里本身就包含了一段响应信息,甚至是响应了一段js代码,或者是响应了一个钓鱼网站会发生什么呢。。小站当然不用担心。。。但,我们这么看中安全测试。。所以你懂的。。。
找到了原因,自然就找到了解决办法。。原谅我bb了这么久。。下面给答案吧。。
public void download(@RequestParam String fileName){
//查询fileInfo的信息
FileInfo fileInfo = service.getFileInfo(fileName);
//处理业务逻辑
//设置响应头,这一行不要直接使用用户入参的fileName以避免http响应被攻击者分割,一定要使用自己系统中定义的名称,如果使用用户(攻击者)的入参进行响应,存在风险。如果代理服务器将攻击者的分割响应挂起(缓存),攻击者再次进行请求的时候会导致用户的下一次响应的缓存命中,这样风险很大,可能导致用户浏览器数据泄露给攻击者
//设置响应头入参时,一定要使用自己系统中的可靠参数
response.setHeader("Content-disposition","attachment;fileName=" + fileInfo.getFileName());
}
附上这个漏洞的原理及攻击方式链接
https://www.doit.com.cn/article/2011-10-14/3422894.shtml
感谢这位大神的解答。其实就是代理服务器将攻击者的响应缓存(挂起)后,攻击者再次请求,导致用户的响应缓存命中。但也并不是代理服务器就一定会让攻击者如愿哈。不过也不能把自己的工资放在别人手里攥着。。所以,不要直接响应用户入参,不要直接响应用户入参,不要直接响应用户入参。