JAVA开发常见安全问题:任意文件下载
·
专栏链接
一、数据的校验
二、认证与授权
三、Cookie与会话管理
四、错误处理
五、日志安全
六、未验证的重定向
数据的校验:任意文件下载
漏洞描述:
在文件下载过程中,程序往往会从前端传入文件的名称或者文件的完整地址用于下载。由于程序中未对“…/”目录跳转字符进行安全过滤,导致攻击者可以下载任意目录下的文件。
检测方法:
检查文件的下载路径是否可以控制(传入的参数值是否为下载路径的一部分)。
检查是否对不可信参数值过滤了“…/”这样的特殊字符,防止下载任意目录下的文件。检查过滤“…/”的代码是否存在可被绕过的危险,过滤应该采用循环过滤的方式,直到过滤完全(即过滤之后的值中不存在“…/”)。
不合规的代码示例:
public String downLoad() throws Exception
{
String fileName =Struts2Utils.getRequest().getParameter("fileName");
try {
fileName = URLDecoder.decode(fileName, "UTF-8");
} catch (UnsupportedEncodingException ex) {
logger.error("downLoad exception"+ ExceptionUtils.getFullStackTrace(ex));
}
String path = SmpConfig.getConfig(CHECK_ATTACHMENT);
File downFile = new File(path + fileName.trim());
HttpServletResponse response =Struts2Utils.getResponse();
try {
if (!downFile.exists()){
response.sendError(404, "File not found!");
return Action.NONE;
}
response.setContentType("application/x-msdownload;chars et=UTF-8");
response.setHeader("Content-Disposition", "attachment; filename="+ new String(this.parseFileName(fileName).getBytes("GBK"),"ISO8859-1"));
OutputStream out = response.getOutputStream();
FileInputStream in = new FileInputStream(downFile);
byte[] buf = new byte[BUFFER_SIZE];
int len = -1;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
in.close();
out.flush();
} catch (Exception ex) {
logger.error("download file exception !".concat(ExceptionUtils.getFullStackTrace(ex)));
}
return Action.NONE;
}
不合规说明:
对于不可信的 fileName 参数,程序将该参数的值组合成完整的文件路径,且未对目录跳转字符(“…/”)进行安全过滤。
合规的代码示例:
public String downLoad() throws Exception {
String fileName =Struts2Utils.getRequest().getParameter("fileName");
try {
fileName = URLDecoder.decode(fileName, "UTF-8");
}
catch (UnsupportedEncodingException ex) {
logger.error("downLoad exception"+ ExceptionUtils.getFullStackTrace(ex));
}
int len1 = 0, len2 = 0;
do {
len1 = fileName.length();
fileName = fileName.replaceAll("\\.\\./", "");
len2 = fileName.length();
} while (len1 != len2);
String path = SmpConfig.getConfig(CHECK_ATTACHMENT);
File downFile = new File(path + fileName.trim());
HttpServletResponse response =Struts2Utils.getResponse();
try {
if (!downFile.exists())
{
response.sendError(404, "File not found!");
return Action.NONE;
}
response.setContentType("application/x-msdownload;chars et=UTF-8");
response.setHeader("Content-Disposition", "attachment;
filename="+ new String(this.parseFileName(fileName).getBytes("GBK"),"ISO8859-1"));
OutputStream out = response.getOutputStream();
FileInputStream in = new FileInputStream(downFile);
byte[] buf = new byte[BUFFER_SIZE];
int len = -1;
while ((len = in.read(buf)) != -1)
{
out.write(buf, 0, len);
}
in.close();
out.flush();
} catch (Exception ex) {
logger.error("download file exception !".concat(ExceptionUtils.getFullStackTrace(ex)));
}
return Action.NONE;
}
合规说明:
对于不可信的 fileName 参数,程序采用循环过滤的方式, 对目录跳转字符(“…/”)进行安全过滤。
更多推荐


所有评论(0)