AppScan 扫描漏洞:Authentication Bypass Using HTTP Verb Tampering(HTTP 动词篡改导致的认证旁路)解决办法

项目在做安全扫描时发现漏洞:Authentication Bypass Using HTTP Verb Tampering(HTTP 动词篡改导致的认证旁路)

扫描报告如下:

风险:可能会升级用户特权并通过 Web 应用程序获取管理许可权可能会收集有关 Web 应用程序的敏感信息,如用户名、密码、机器名和 / 或敏感文件位置

Fix:Configure your server to allow only required HTTP methods

以下更改已应用到原始请求:

已将 方法 设置为“BOGUS”

推理:

The test result seems to indicate a vulnerability because the Test Response is identical to the Original Response, indicating that the verb tampering was able to bypass the site authentication

大概意思就是,使用不安全的 HTTP 请求方式请求接口,却得到了看似有效的返回。

解决办法

我们知道,HTTP 支持很多种请求方式,但是一般的项目大部分用的还是 GET,POST,PUT,DELETE,HEAD 等常见的请求方式。

所以解决办法就是,让服务器或应用只支持项目中用到的几种请求方式,其它的都拒绝请求。比如:返回 405 状态码。

第一种办法(需要 Tomcat9 以上版本):

配置使用的 Tomcat 服务器支持的http-method,配置文件在:$CATALINA_BASE/conf/web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<security-constraint>
<web-resource-collection>
<http-method>HEAD</http-method>
<http-method>GET</http-method>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name></role-name>
</auth-constraint>
</security-constraint>

第二种办法:

在应用代码中加个 Filter,判断请求方式,不支持的直接拒绝,代码如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.io.IOException;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpMethod;

import com.google.common.collect.Sets;

public class HttpMethodFilter implements Filter {

/**
* 本项目用到的 HTTP 请求方式,其它的都不被接受。
*/
private static final Set<String> ALLOWED_HTTP_METHOD = Sets.newHashSet(
HttpMethod.HEAD.toString(),
HttpMethod.GET.toString(),
HttpMethod.POST.toString(),
HttpMethod.DELETE.toString(),
HttpMethod.OPTIONS.toString()
);

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;

// 为了抵御不安全的 HTTP 请求方式的攻击,通过 Filter 限定只能支持某些 HTTP 请求方法。
if (!ALLOWED_HTTP_METHOD.contains(StringUtils.upperCase(req.getMethod()))) {
resp.getWriter().write("Return from filter, unsupported http method:" + req.getMethod());
resp.setStatus(405);
return;
}

chain.doFilter(request, response);
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void destroy() {

}
}