Java路径遍历漏洞修复心得

Java路径遍历漏洞修复心得一、路径遍历路径遍历是指应用程序接收了未经合理校验的用户参数用于进行与文件读取查看相关操作,而该参数包含了特殊的字符(例如“..”和“/”),使用了这类特殊字符可以摆脱受保护的限制,越权访问一些受保护的文件、目录或者覆盖敏感数据。本文以JAVA语言源代码为例,分析路径遍历缺陷及该缺陷产生的原因及修复方法。二、缺陷代码172行因为localFile因为接收参数后未对参数做合理校验,可能会收到../file.text,假定文件路径有效,则可能导致读取了uploads父目录下的file.t

一、路径遍历

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

二、缺陷代码

Java路径遍历漏洞修复心得

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<String> 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路径遍历漏洞修复心得

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

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

今天的文章Java路径遍历漏洞修复心得分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/8970.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注