java - 在 Servlet 中编写 HTTP 响应时的跨站点脚本漏洞(下载 excel 文件)
问题描述
以下代码容易受到veracode扫描报告的跨站点脚本攻击:
public void doPost(HttpServletRequest request,HttpServletResponse response)
{
byte[] inputBytes = request.getParameter("input").getBytes();
String name = request.getParameter("filename") == null?"excelReport":request.getParameter("filename").toString();
response.setContentType("application/vnd.ms-excel");
response.setContentLength(inputBytes.length);
response.addHeader("content-disposition", "attachment; filename="+name+".xls");
try {
response.getOutputStream().write(inputBytes, 0, inputBytes.length);
} catch (IOException e) {
e.printStackTrace();
}
}
我理解这行代码 -response.getOutputStream().write(inputBytes, 0, inputBytes.length);
容易受到 XSS 攻击。
如何在这里修复 XSS(跨站点脚本)漏洞?是否有任何 ESAPI 库可用于 byte[] 数组来修复 XSS 缺陷?
解决方案
要采用良好的深度防御方法来防止 XSS,需要做两件事。
- 输出编码
- 输入验证
您的代码有几个安全问题,而不仅仅是 XSS。但要完成您的主要问题,OWASP 的 ESAPI 有一个编码器,还有 ESAPI Encoder 项目。正确的方法是在将编码器交给解释器时尽可能接近地使用编码器。由于您使用的是 JSP,因此您需要对显示给用户的任何输出进行编码,以保证他们的安全。
你的其他问题:
public void doPost(HttpServletRequest request,HttpServletResponse response)
{
//Did we get the correct file?
byte[] inputBytes = request.getParameter("input").getBytes();
//Validation against legal characters in the filename?
String name = request.getParameter("filename") == null?"excelReport":request.getParameter("filename").toString();
response.setContentType("application/vnd.ms-excel");
response.setContentLength(inputBytes.length);
//This is the line that's immediately triggering your problem. The attacker controls that filename and you've done nothing to check it!
//If you encoded here you MIGHT be fine!
response.addHeader("content-disposition", "attachment; filename="+name+".xls");
try {
response.getOutputStream().write(inputBytes, 0, inputBytes.length);
} catch (IOException e) {
e.printStackTrace();
}
}
如果您想了解此漏洞,请使用类似 OWASP 的 ZAP 之类的工具并将文件名参数修改为类似的值<script>alert(1);</script>
,您将看到该漏洞正在运行。
至于文件本身,ESAPI 只提供了检查文件扩展名白名单的方法,它不是很好,但文件验证实际上很难正确进行。所以不,没有方法可以验证您的文件字节。