Java路径遍历漏洞修复心得

一、路径遍历

路径遍历是指应用程序接收了未经合理校验的用户参数用于进行与文件读取查看相关操作,而该参数包含了特殊的字符(例如“..”和“/”),使用了这类特殊字符可以摆脱受保护的限制,越权访问一些受保护的文件、目录或者覆盖敏感数据。本文以JAVA 语言源代码为例,分析路径遍历缺陷及该缺陷产生的原因及修复方法。

二、缺陷代码

Java路径遍历漏洞修复心得_第1张图片

172行因为localFile因为接收参数后未对参数做合理校验,可能会收到../file.text,假定文件路径有效,则可能导致读取了 uploads 父目录下的 file.text 文件。

三、代码修复

我使用了2种方法可以来解决路径遍历问题,一是全局过滤,二是单个字符串过滤

全局过滤代码如下:

private String fileNameValidate(String str) {
		
		String fileNameListStr ="../|./|/..";  //这里为请求体中不能携带的关键字

		if(null!=fileNameListStr && !"".equals(fileNameListStr))
		{
			str = str.toLowerCase();// 统一转为小写

			log.info("sqlFilter===========================>>路径遍历过滤规则:"+ fileNameListStr);

			String[] badStrs = fileNameListStr.split("\\|");
			for (int i = 0; i < badStrs.length; i++) {
				if (str.indexOf(badStrs[i]) >= 0) {
					return badStrs[i];
				}
			}
		}
		return null;
	}

我配置的过滤器

public class FlieNameFilter implements Filter{
	
	private static final Logger log = LoggerFactory.getLogger(FlieNameFilter.class);
	private ResourceBundle bundle;

	@Override
	public void destroy() {
		bundle = null;
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;

		// 获得所有请求参数名
		Enumeration params = req.getParameterNames();
		StringBuffer content = new StringBuffer("");
		while (params.hasMoreElements()) {
			// 得到参数名
			String name = params.nextElement().toString();

			String value = req.getParameter(name);
			
			content.append(value);
		}

		String sqlInjectListStr = bundle.getString("fileNameListStr");
		
		String message = fileNameValidate(content.toString(), sqlInjectListStr);

		if (message != null) {
			req.getSession().setAttribute("overpowerMessage", message);
			log.error("sqlFilter============================>>error!! find fileName inject.");
			log.error("sqlFilter============================>>传入的参数字符串:"+ content.toString());
			res.sendRedirect(req.getContextPath() + "/overpower.jsp");
		} else {
			chain.doFilter(request, response);
		}
	}

	private String fileNameValidate(String str, String sqlInjectListStr) {
		

		if(null!=sqlInjectListStr && !"".equals(sqlInjectListStr))
		{
			str = str.toLowerCase();// 统一转为小写

			log.info("sqlFilter===========================>>路径遍历过滤规则:"+ sqlInjectListStr);

			String[] badStrs = sqlInjectListStr.split("\\|");
			for (int i = 0; i < badStrs.length; i++) {
				if (str.indexOf(badStrs[i]) >= 0) {
					return badStrs[i];
				}
			}
		}
		return null;
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		try {
			bundle = new PropertyResourceBundle(this.getClass().getClassLoader().getResourceAsStream("parameters.properties"));
		} catch (IOException e) {
			log.error("parameters.properties配置文件夹在失败");
		}
	}
	
	
}

我的匹配规则是写在配置文件中,所以先读取配置文件来获取匹配规则。如果请求体中有../这样的危险字符串,就会拦截返回异常页面。这样写也是有缺陷的,就是你在填写文档或日志描述时不能填写../等匹配规则的危险字符串。

第二种是单体字符串过滤:

public class FlieNamefilter {

	//private static Pattern FilePattern = Pattern.compile("[\\\\/:*?\"<>|]"); 
	
	private static Pattern FilePattern = Pattern.compile("[\\s\\.:?<>|]"); //过滤规则
	
	public static String filenameFilter(String str) {  
		return str==null?null:FilePattern.matcher(str).replaceAll("");  
	}
	
	public static void main(String[] args) {
		String str="home/..  <>|logs/../:edata?";
		//String filenameFilter = filenameFilter(str);
        String filenameFilter = fileNameValidate(str);
		System.out.println(filenameFilter);
	}
	
}


 private static String fileNameValidate(String str) {
		
	   String strInjectListStr ="../|./|/..| |<|>|:|?";
		if(null!=strInjectListStr && !"".equals(strInjectListStr))
		{
			str = str.toLowerCase();
			String[] badStrs = strInjectListStr.split("\\|");
			for (int i = 0; i < badStrs.length; i++) {
				if (str.indexOf(badStrs[i]) >= 0) {
				 str= str.replace(badStrs[i], "");
				}
			}
		}
		return str;
	}

在单个字符串过滤的情况下,如果路径遍历漏洞很多,那就需要改很多地方了。

四、代码安全卫士测试

有些小伙伴可能写了这些代码发布到安全测试上去,发现自己的路径遍历漏洞还存在,那么我也是碰到这样的坑了。需要联系你们测试代码工具的人去聊这个问题。其实路径遍历的问题已经解决了比如:

Java路径遍历漏洞修复心得_第2张图片

找官方人员说 引擎不知道咱们上面写的代码是用来做路径遍历过滤的,所以要告诉引擎。方法是把处理逻辑封装成一个方法,然后再系统管理-函数白名单中配置,然后发起检测的时候,选在这个白名单函数。
或者直接审计为不是问题,如果选择了审计携带,下次检测后会审计为不是问题。说白了就是漏洞已经修复了,但是他没有检测到你修改的代码。

好了,以上就是我碰到的问题,有喜欢的点个赞,关注一下作者!

你可能感兴趣的:(java,安全漏洞)