1. 背景说明
Web安全测试中,会要求屏蔽非必要的不安全Http请求方法。一般要求保留get和post,其他的方法一般屏蔽,比如:OPTIONS,DELETE等。
本文主要收集业务系统中,不同时期,我们框架的各版本的处理方案,都基于tomcat+spring各版本体系。
2. 解决思路
使用tomcat自带的安全认证机制。配置对应的URL下的http方法访问都需要认证,但不配置认证方式,以实现对不安全的http方法的控制访问。主要应用的配置,原理上通过web.xml中的security-constraint节点进行定义。
具体相关参数的配置说明如下:
- web-resource-collection:此元素确定应该保护的资源。包含几个特定的子元素:
- url-pattern:表示受控的URL路径。
- http-method:表示受控的http请求方法。例如:OPTIONS
- http-method-omission:表示忽悠受控的http请求方法
- auth-constraint:指出哪些用户应该具有受保护资源的访问权,正常情况应该包含一个或多个标识具有访问权限的用户类别role-name元素。如果没有 <auth-constraint>这表明任何身份的用户都可以访问相应的资源,如果加入了 <auth-constraint> 子元素,但是其内容为空,这表示所有身份的用户都被禁止访问相应的资源。对应
SecurityConstraint.setAuthConstraint(true);
- user-data-constraint:可选的元素指出在访问相关资源时使用任何传输层保护。它必须包含一个transport-guarantee子元素
- NONE:对所用的通讯协议不加限制
- CONFIDENTIAL:他们都只是简单地要求用SSL,一般是自动采用30x跳转。Api方式:
SecurityConstraint.setUserConstraint("CONFIDENTIAL");
- INTEGRAL:类似CONFIDENTIAL
3. 解决方案
3.1 直接Tomcat部署
这种方式一般是在应用springboot前的模式,包括:spring2-spring4时代。采用直接修改工程的Web.xml来解决。
在你工程的web.xml中配置:
- 配置需要禁用的HTTP方法
<security-constraint>
<web-resource-collection>
<web-resource-name>acooly-default-policy</web-resource-name>
<!-- 表示需要认证控制的URL -->
<url-pattern>/*</url-pattern>
<!-- 以下多个是表示允许的http请求方法 -->
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
<http-method>HEAD</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
</web-resource-collection>
<!-- 表示:需要认证 -->
<auth-constraint/>
</security-constraint>
- 配置允许访问的HTTP方法
<security-constraint>
<web-resource-collection>
<web-resource-name>acooly-default-policy</web-resource-name>
<!-- 表示需要认证控制的URL -->
<url-pattern>/*</url-pattern>
<!--
以下多个是表示允许的http请求方法
注意:实测区分大小写
-->
<http-method-omission>POST</http-method-omission>
<http-method-omission>post</http-method-omission>
<http-method-omission>GET</http-method-omission>
<http-method-omission>get</http-method-omission>
</web-resource-collection>
<!-- 表示:需要认证 -->
<auth-constraint/>
</security-constraint>
以上两种方式,推荐使用:“配置允许访问的HTTP方法”
3.2 springboot1.x
使用springboot的autoconfig特性,为tomcat增加扩展的自动配置功能。
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass(Tomcat.class)
public class TomcatAutoConfig {
@Bean(name = "tomcatEmbeddedServletContainerFactory")
public EmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setAuthConstraint(true);
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
collection.addOmittedMethod("GET");
collection.addOmittedMethod("get");
collection.addOmittedMethod("post");
collection.addOmittedMethod("POST");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
return tomcat;
}
}
3.3 springboot2.x
原理同springboot1.x,只是在2.x版本后,可以直接采用TomcatServletWebServerFactory.addContextCustomizers
发放增加ContextCustomizer扩展。
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass(Tomcat.class)
public class TomcatAutoConfig {
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> acoolyWebServerFactoryCustomizer() {
return factory -> {
// 禁用内置Tomcat的不安全请求方法
factory.addContextCustomizers(context -> {
SecurityConstraint securityConstraint = new SecurityConstraint();
// 开启认证
securityConstraint.setAuthConstraint(true);
SecurityCollection collection = new SecurityCollection();
// 对所有资源生效
collection.addPattern("/*");
// 以下是排除认证的非安全http方法(安全的方法)
collection.addOmittedMethod("GET");
collection.addOmittedMethod("get");
collection.addOmittedMethod("POS");
collection.addOmittedMethod("post");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
});
};
}
}