专栏链接

一、数据的校验

  1. SQL注入
  2. 命令注入
  3. 跨站脚本
  4. 任意文件上传
  5. 任意文件下载
  6. 任意文件删除
  7. 任意文件读取与写入
  8. Iframe 框架钓鱼
  9. 负值支付漏洞

二、认证与授权

  1. 密码修改(无需原密码)
  2. 密码策略不足
  3. 用户名密码(敏感信息)明文传输
  4. 验证码可重复利用
  5. 缺少验证码功能
  6. 用户名枚举(用户名和密码单独验证)
  7. 登录尝试次数限制功能失效
  8. 登录后门
  9. 横向越权
  10. 纵向越权

三、Cookie与会话管理

  1. 直接关闭浏览器“退出“系统
  2. 会话标识未更新
  3. Cookie 中明文存储用户名、密码

四、错误处理

  1. 数据库交互中的异常处理

五、日志安全

  1. 日志记录敏感信息

六、未验证的重定向

  1. URL 重定向

数据的校验:任意文件下载

漏洞描述:

在文件下载过程中,程序往往会从前端传入文件的名称或者文件的完整地址用于下载。由于程序中未对“…/”目录跳转字符进行安全过滤,导致攻击者可以下载任意目录下的文件。

检测方法:

检查文件的下载路径是否可以控制(传入的参数值是否为下载路径的一部分)。

检查是否对不可信参数值过滤了“…/”这样的特殊字符,防止下载任意目录下的文件。检查过滤“…/”的代码是否存在可被绕过的危险,过滤应该采用循环过滤的方式,直到过滤完全(即过滤之后的值中不存在“…/”)。

不合规的代码示例:

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 参数,程序采用循环过滤的方式, 对目录跳转字符(“…/”)进行安全过滤。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐