聊聊directory traversal attack

本文主要研究一下directory traversal attack及其防范

directory traversal attack

又称Path Traversal attack,即目录遍历攻击,旨在访问web服务器根目录外的文件/目录。通过是通过url或变量里头传递"../"来进行目录遍历。

通过url

比如

http://some_site.com.br/../../../../some dir/some file 
复制代码

或者

http://some_site.com.br/../../../../etc/shadow 
复制代码

通过变量名

通常是在文件下载接口中,比如

http://some_site.com.br/get-files?file=/etc/passwd 
复制代码

或者

http://some_site.com.br/get-files?file=../../../../some dir/some file 
复制代码

防范

针对url

spring security提供了DefaultHttpFirewall来进行处理,是为了防止一些web框架没有遵循servlet规范而进行的防范。 spring-security-web-4.2.3.RELEASE-sources.jar!/org/springframework/security/web/firewall/DefaultHttpFirewall.java

/**
 * Default implementation which wraps requests in order to provide consistent
 * values of the {@code servletPath} and {@code pathInfo}, which do not contain
 * path parameters (as defined in
 * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>). Different
 * servlet containers interpret the servlet spec differently as to how path
 * parameters are treated and it is possible they might be added in order to
 * bypass particular security constraints. When using this implementation, they
 * will be removed for all requests as the request passes through the security
 * filter chain. Note that this means that any segments in the decoded path
 * which contain a semi-colon, will have the part following the semi-colon
 * removed for request matching. Your application should not contain any valid
 * paths which contain semi-colons.
 * <p>
 * If any un-normalized paths are found (containing directory-traversal
 * character sequences), the request will be rejected immediately. Most
 * containers normalize the paths before performing the servlet-mapping, but
 * again this is not guaranteed by the servlet spec.
 *
 * @author Luke Taylor
 */
public class DefaultHttpFirewall implements HttpFirewall {
	private boolean allowUrlEncodedSlash;

	@Override
	public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
		FirewalledRequest fwr = new RequestWrapper(request);

		if (!isNormalized(fwr.getServletPath()) || !isNormalized(fwr.getPathInfo())) {
			throw new RequestRejectedException("Un-normalized paths are not supported: " + fwr.getServletPath()
					+ (fwr.getPathInfo() != null ? fwr.getPathInfo() : ""));
		}

		String requestURI = fwr.getRequestURI();
		if (containsInvalidUrlEncodedSlash(requestURI)) {
			throw new RequestRejectedException("The requestURI cannot contain encoded slash. Got " + requestURI);
		}

		return fwr;
	}

	@Override
	public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
		return new FirewalledResponse(response);
	}

	/**
	 * <p>
	 * Sets if the application should allow a URL encoded slash character.
	 * </p>
	 * <p>
	 * If true (default is false), a URL encoded slash will be allowed in the
	 * URL. Allowing encoded slashes can cause security vulnerabilities in some
	 * situations depending on how the container constructs the
	 * HttpServletRequest.
	 * </p>
	 *
	 * @param allowUrlEncodedSlash
	 *            the new value (default false)
	 */
	public void setAllowUrlEncodedSlash(boolean allowUrlEncodedSlash) {
		this.allowUrlEncodedSlash = allowUrlEncodedSlash;
	}

	private boolean containsInvalidUrlEncodedSlash(String uri) {
		if (this.allowUrlEncodedSlash || uri == null) {
			return false;
		}

		if (uri.contains("%2f") || uri.contains("%2F")) {
			return true;
		}

		return false;
	}

	/**
	 * Checks whether a path is normalized (doesn't contain path traversal
	 * sequences like "./", "/../" or "/.")
	 *
	 * @param path
	 *            the path to test
	 * @return true if the path doesn't contain any path-traversal character
	 *         sequences.
	 */
	private boolean isNormalized(String path) {
		if (path == null) {
			return true;
		}

		for (int j = path.length(); j > 0;) {
			int i = path.lastIndexOf('/', j - 1);
			int gap = j - i;

			if (gap == 2 && path.charAt(i + 1) == '.') {
				// ".", "/./" or "/."
				return false;
			} else if (gap == 3 && path.charAt(i + 1) == '.' && path.charAt(i + 2) == '.') {
				return false;
			}

			j = i;
		}

		return true;
	}

}
复制代码

这里会对url进行判断

通过变量

这种框架没有内置进行判断,需要自己在开发应用服务的时候额外关注。这里谈谈几种防范方法。

  • 对变量名进行过滤
final Pattern INVALID_PATH_PATTERN = Pattern.compile("(\\.\\.\\/|\\.\\.\\\\)");
if(INVALID_PATH_PATTERN.matcher(path).find()){
	throw new BadRequestException("invalid path");
}
复制代码
  • 利用absolutePath与canonicalPath

absolutePath不会处理../之类的,而canonicalPath会翻译../,判断两者是否相等即可判断是否有../

        if (!file.getAbsolutePath().equals(file.getCanonicalPath())) {
            throw new BadRequestException("invalid path");
        }
复制代码

小结

在编写文件下载服务的时候,需要特别关注directory traversal attack。通常url层面的web框架会帮你防范,但是变量层面的,则需要自己开发额外注意。

doc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值