本文于2016年4月完成,发布在个人博客网站上。 <constant name="struts.action.extension" value="jsp,action"/>考虑个人博客因某种原因无法修复,于是在博客园安家,之前发布的文章逐步搬迁过来。
诡异的问题
分析AppScan扫描报告的时候,发现报告里提示“HTTP动词篡改导致的认证旁路”,一个名字很长,很怪异的问题。咨询度娘没有获取到必要的信息,于是只好按照AppScan报告里给出的重现步骤,实地操作来看看。
AppScan给出的复现步骤很简单,如下:
- 使用burpsuite拦截浏览器发出的HTTP请求,如下为样例:
- <constant name="struts.action.extension" value="jsp,action"/>GET <constant name="struts.action.extension" value="jsp,action"/>/index.jsp <constant name="struts.action.extension" value="jsp,action"/>HTTP/1.1
- <constant name="struts.action.extension" value="jsp,action"/>Host: <constant name="struts.action.extension" value="jsp,action"/>127.0.0.1:8080
- <constant name="struts.action.extension" value="jsp,action"/>Cache-Control: <constant name="struts.action.extension" value="jsp,action"/>max-age=0
- <constant name="struts.action.extension" value="jsp,action"/>Accept: <constant name="struts.action.extension" value="jsp,action"/>text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
- <constant name="struts.action.extension" value="jsp,action"/>Upgrade-Insecure-Requests: <constant name="struts.action.extension" value="jsp,action"/>1
- <constant name="struts.action.extension" value="jsp,action"/>User-Agent: <constant name="struts.action.extension" value="jsp,action"/>Mozilla/5.0 <constant name="struts.action.extension" value="jsp,action"/>(Windows <constant name="struts.action.extension" value="jsp,action"/>NT <constant name="struts.action.extension" value="jsp,action"/>10.0; <constant name="struts.action.extension" value="jsp,action"/>WOW64) <constant name="struts.action.extension" value="jsp,action"/>AppleWebKit/537.36 <constant name="struts.action.extension" value="jsp,action"/>(KHTML, <constant name="struts.action.extension" value="jsp,action"/>like <constant name="struts.action.extension" value="jsp,action"/>Gecko) <constant name="struts.action.extension" value="jsp,action"/>Chrome/48.0.2564.116 <constant name="struts.action.extension" value="jsp,action"/>Safari/537.36
- <constant name="struts.action.extension" value="jsp,action"/>Accept-Encoding: <constant name="struts.action.extension" value="jsp,action"/>gzip, <constant name="struts.action.extension" value="jsp,action"/>deflate, <constant name="struts.action.extension" value="jsp,action"/>sdch
- <constant name="struts.action.extension" value="jsp,action"/>Accept-Language: <constant name="struts.action.extension" value="jsp,action"/>zh-CN,zh;q=0.8
- <constant name="struts.action.extension" value="jsp,action"/>Connection: <constant name="struts.action.extension" value="jsp,action"/>close
复制代码 - 修改HTTP方法,比如把GET修改为BOGUS,然后点击Forward,把请求转发给Web服务器。
- <constant name="struts.action.extension" value="jsp,action"/>BOGUS <constant name="struts.action.extension" value="jsp,action"/>/index.jsp <constant name="struts.action.extension" value="jsp,action"/>HTTP/1.1
- <constant name="struts.action.extension" value="jsp,action"/>Host: <constant name="struts.action.extension" value="jsp,action"/>127.0.0.1:8080
- <constant name="struts.action.extension" value="jsp,action"/>Cache-Control: <constant name="struts.action.extension" value="jsp,action"/>max-age=0
- <constant name="struts.action.extension" value="jsp,action"/>Accept: <constant name="struts.action.extension" value="jsp,action"/>text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
- <constant name="struts.action.extension" value="jsp,action"/>Upgrade-Insecure-Requests: <constant name="struts.action.extension" value="jsp,action"/>1
- <constant name="struts.action.extension" value="jsp,action"/>User-Agent: <constant name="struts.action.extension" value="jsp,action"/>Mozilla/5.0 <constant name="struts.action.extension" value="jsp,action"/>(Windows <constant name="struts.action.extension" value="jsp,action"/>NT <constant name="struts.action.extension" value="jsp,action"/>10.0; <constant name="struts.action.extension" value="jsp,action"/>WOW64) <constant name="struts.action.extension" value="jsp,action"/>AppleWebKit/537.36 <constant name="struts.action.extension" value="jsp,action"/>(KHTML, <constant name="struts.action.extension" value="jsp,action"/>like <constant name="struts.action.extension" value="jsp,action"/>Gecko) <constant name="struts.action.extension" value="jsp,action"/>Chrome/48.0.2564.116 <constant name="struts.action.extension" value="jsp,action"/>Safari/537.36
- <constant name="struts.action.extension" value="jsp,action"/>Accept-Encoding: <constant name="struts.action.extension" value="jsp,action"/>gzip, <constant name="struts.action.extension" value="jsp,action"/>deflate, <constant name="struts.action.extension" value="jsp,action"/>sdch
- <constant name="struts.action.extension" value="jsp,action"/>Accept-Language: <constant name="struts.action.extension" value="jsp,action"/>zh-CN,zh;q=0.8
- <constant name="struts.action.extension" value="jsp,action"/>Connection: <constant name="struts.action.extension" value="jsp,action"/>close
复制代码 - 令人大跌眼镜的事情发生了,Web服务器居然返回了HTTP <constant name="struts.action.extension" value="jsp,action"/>200,同时正确的返回了页面;
顿时让人有点小郁闷。按照产品线要求,当前所在项目使用的是平台部门基于Apache <constant name="struts.action.extension" value="jsp,action"/>Tomcat <constant name="struts.action.extension" value="jsp,action"/>7.0.x源码做过加固的版本,按理说不该存在类似的安全问题。
对照Tomcat加固要求,重新检查了$CATALINA_BASE/conf/web.xml,确认其中包含了如下配置,这说明已经屏蔽了不安全的HTTP方法,应该是没有问题才对。- <security-constraint>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><web-resource-collection>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><http-method>HEAD</http-method>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><http-method>PUT</http-method>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><http-method>DELETE</http-method>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><http-method>OPTIONS</http-method>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><http-method>TRACE</http-method>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><url-pattern>/*</url-pattern>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/></web-resource-collection>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><auth-constraint>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><role-name></role-name>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/></auth-constraint>
- </security-constraint>
复制代码 那么为什么AppScan扫描报告中出现了前述问题,Jackie一时有些想不明白。
项目的技术特点
当前所在项目使用了Spring+Struts2+iBatis,从技术组合上可以说非常传统,但在技术应用上存在很大不同,比如:
- 浏览器请求页面时,使用通用Action将请求重定向至对应的jsp页面;
- 页面上使用jQuery提供的ajax对象来加载呈现需要的数据;
- 为了实现项目国际化的需求,要求所有对jsp的请求都需要经过通用Action的转发;
- 页面代码使用Struts2的s标签来提取国际化信息;
这样的应用方式其实有不得以的苦衷,项目刚成立的时候,组内全是新人,对Struts2仅有名义上的理解,没有人在项目中实际运用中使用Struts2,另外项目进度压的很紧,没时间给大家去了解和学习;而使用ajax来实现页面与Web服务之间通信,实现和使用都简单,于是一直沿用至今。
Struts2的配置
Struts2在web.xml中的配置如下:- <filter>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><filter-name>struts2</filter-name>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
- </filter>
- <filter-mapping>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><filter-name>struts2</filter-name>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><url-pattern>/*</url-pattern>
- </filter-mapping>
复制代码 简化后的struts.xml配置文件,内容如下:- <?xml <constant name="struts.action.extension" value="jsp,action"/>version="1.0" <constant name="struts.action.extension" value="jsp,action"/>encoding="UTF-8" <constant name="struts.action.extension" value="jsp,action"/>?>
- <!DOCTYPE <constant name="struts.action.extension" value="jsp,action"/>struts <constant name="struts.action.extension" value="jsp,action"/>PUBLIC
- "-//Apache <constant name="struts.action.extension" value="jsp,action"/>Software <constant name="struts.action.extension" value="jsp,action"/>Foundation//DTD <constant name="struts.action.extension" value="jsp,action"/>Struts <constant name="struts.action.extension" value="jsp,action"/>Configuration <constant name="struts.action.extension" value="jsp,action"/>2.3//EN"
- "http://struts.apache.org/dtds/struts-2.3.dtd">
- <struts>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><constant <constant name="struts.action.extension" value="jsp,action"/>name="struts.enable.DynamicMethodInvocation" <constant name="struts.action.extension" value="jsp,action"/>value="false" <constant name="struts.action.extension" value="jsp,action"/>/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><constant <constant name="struts.action.extension" value="jsp,action"/>name="struts.devMode" <constant name="struts.action.extension" value="jsp,action"/>value="true" <constant name="struts.action.extension" value="jsp,action"/>/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><constant <constant name="struts.action.extension" value="jsp,action"/>name="struts.action.extension" <constant name="struts.action.extension" value="jsp,action"/>value="jsp,action"/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><constant <constant name="struts.action.extension" value="jsp,action"/>name="struts.ui.theme" <constant name="struts.action.extension" value="jsp,action"/>value="java"></constant>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><constant <constant name="struts.action.extension" value="jsp,action"/>name="struts.objectFactory" <constant name="struts.action.extension" value="jsp,action"/>value="spring" <constant name="struts.action.extension" value="jsp,action"/>/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><constant <constant name="struts.action.extension" value="jsp,action"/>name="struts.i18n.encoding" <constant name="struts.action.extension" value="jsp,action"/>value="UTF-8" <constant name="struts.action.extension" value="jsp,action"/>/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><package <constant name="struts.action.extension" value="jsp,action"/>name="default" <constant name="struts.action.extension" value="jsp,action"/>namespace="/" <constant name="struts.action.extension" value="jsp,action"/>extends="struts-default">
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><interceptors>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><interceptor-stack <constant name="struts.action.extension" value="jsp,action"/>name="myStack"> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><interceptor-ref <constant name="struts.action.extension" value="jsp,action"/>name="basicStack"></interceptor-ref> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/></interceptor-stack> <constant name="struts.action.extension" value="jsp,action"/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/></interceptors> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><default-interceptor-ref <constant name="struts.action.extension" value="jsp,action"/>name="myStack" <constant name="struts.action.extension" value="jsp,action"/>/> <constant name="struts.action.extension" value="jsp,action"/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><global-results>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><result <constant name="struts.action.extension" value="jsp,action"/>name="error">/error.jsp</result>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/></global-results>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><global-exception-mappings>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><exception-mapping <constant name="struts.action.extension" value="jsp,action"/>exception="java.lang.Exception" <constant name="struts.action.extension" value="jsp,action"/>result="error"/>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/></global-exception-mappings>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><action <constant name="struts.action.extension" value="jsp,action"/>name="*" <constant name="struts.action.extension" value="jsp,action"/>>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/><result <constant name="struts.action.extension" value="jsp,action"/>name="success">{1}.jsp</result>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/></action>
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/></package>
- </struts>
复制代码 通用Action类,简化后的MainAction代码如下- import <constant name="struts.action.extension" value="jsp,action"/>com.opensymphony.xwork2.ActionSupport;
- public <constant name="struts.action.extension" value="jsp,action"/>class <constant name="struts.action.extension" value="jsp,action"/>MainAction <constant name="struts.action.extension" value="jsp,action"/>extends <constant name="struts.action.extension" value="jsp,action"/>ActionSupport <constant name="struts.action.extension" value="jsp,action"/>{
- private <constant name="struts.action.extension" value="jsp,action"/>static <constant name="struts.action.extension" value="jsp,action"/>final <constant name="struts.action.extension" value="jsp,action"/>long <constant name="struts.action.extension" value="jsp,action"/>serialVersionUID <constant name="struts.action.extension" value="jsp,action"/>= <constant name="struts.action.extension" value="jsp,action"/>928135783255954591L;
- @Override
- public <constant name="struts.action.extension" value="jsp,action"/>String <constant name="struts.action.extension" value="jsp,action"/>execute() <constant name="struts.action.extension" value="jsp,action"/>throws <constant name="struts.action.extension" value="jsp,action"/>Exception <constant name="struts.action.extension" value="jsp,action"/>{
- return <constant name="struts.action.extension" value="jsp,action"/>ActionSupport.SUCCESS;
- }
- }
复制代码 从配置上讲,中规中矩,并没有什么特别的地方。
分析过程
访问jsp页面的流程
按照前述配置,当用户在浏览器地址栏里输入后缀为.jsp的url,敲击回车后,发生的事件如下:
- 由于在struts.xml文件中有如下配置,用户请求先被Struts2拦截;
- <constant name="struts.action.extension" value="jsp,action"/>
复制代码 - 由于在struts.xml中有如下配置,请求会被转发给MainAction来处理;
- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>{1}.jsp <constant name="struts.action.extension" value="jsp,action"/>
复制代码 - 由于MainAction类的execute方法只返回了"success",于是请求又被重定向回了对应的jsp页面;
- <constant name="struts.action.extension" value="jsp,action"/>@Override <constant name="struts.action.extension" value="jsp,action"/>public <constant name="struts.action.extension" value="jsp,action"/>String <constant name="struts.action.extension" value="jsp,action"/>execute() <constant name="struts.action.extension" value="jsp,action"/>throws <constant name="struts.action.extension" value="jsp,action"/>Exception <constant name="struts.action.extension" value="jsp,action"/>{ <constant name="struts.action.extension" value="jsp,action"/> return <constant name="struts.action.extension" value="jsp,action"/>ActionSupport.SUCCESS; <constant name="struts.action.extension" value="jsp,action"/>}
复制代码 - 这时,对jsp页面的访问就由Tomcat接管了;
与9.0.x版本的Tomcat做对比
按照上面的分析,在第4步,如果Tomcat遇到了异常的请求方法,应该拒绝响应才是,不应当返回HTTP <constant name="struts.action.extension" value="jsp,action"/>200和页面。那么会不会是Tomcat实现存在问题?
平台发布加固后的Tomcat版本时并没有附带源码,于是从官网获取Tomcat发布的9.0.x版本做对比验证。执行前述的复现步骤,Tomcat <constant name="struts.action.extension" value="jsp,action"/>9.0.x版本给浏览器返回了如下响应:- HTTP <constant name="struts.action.extension" value="jsp,action"/>Status <constant name="struts.action.extension" value="jsp,action"/>405 <constant name="struts.action.extension" value="jsp,action"/>- <constant name="struts.action.extension" value="jsp,action"/>JSPs <constant name="struts.action.extension" value="jsp,action"/>only <constant name="struts.action.extension" value="jsp,action"/>permit <constant name="struts.action.extension" value="jsp,action"/>GET <constant name="struts.action.extension" value="jsp,action"/>POST <constant name="struts.action.extension" value="jsp,action"/>or <constant name="struts.action.extension" value="jsp,action"/>HEADtype <constant name="struts.action.extension" value="jsp,action"/>Status <constant name="struts.action.extension" value="jsp,action"/>reportmessage <constant name="struts.action.extension" value="jsp,action"/>JSPs <constant name="struts.action.extension" value="jsp,action"/>only <constant name="struts.action.extension" value="jsp,action"/>permit <constant name="struts.action.extension" value="jsp,action"/>GET <constant name="struts.action.extension" value="jsp,action"/>POST <constant name="struts.action.extension" value="jsp,action"/>or <constant name="struts.action.extension" value="jsp,action"/>HEADdescription <constant name="struts.action.extension" value="jsp,action"/>The <constant name="struts.action.extension" value="jsp,action"/>specified <constant name="struts.action.extension" value="jsp,action"/>HTTP <constant name="struts.action.extension" value="jsp,action"/>method <constant name="struts.action.extension" value="jsp,action"/>is <constant name="struts.action.extension" value="jsp,action"/>not <constant name="struts.action.extension" value="jsp,action"/>allowed <constant name="struts.action.extension" value="jsp,action"/>for <constant name="struts.action.extension" value="jsp,action"/>the <constant name="struts.action.extension" value="jsp,action"/>requested <constant name="struts.action.extension" value="jsp,action"/>resource.
复制代码 检查9.0.x版本Tomcat生成的servlet代码,发现在_jspService中增加了对HTTP方法有效性的校验,只允许jsp编译生成的servlet响应GET、POST或HEAD方法,如下。- <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>public <constant name="struts.action.extension" value="jsp,action"/>void <constant name="struts.action.extension" value="jsp,action"/>_jspService(final <constant name="struts.action.extension" value="jsp,action"/>javax.servlet.http.HttpServletRequest <constant name="struts.action.extension" value="jsp,action"/>request, <constant name="struts.action.extension" value="jsp,action"/>final <constant name="struts.action.extension" value="jsp,action"/>javax.servlet.http.HttpServletResponse <constant name="struts.action.extension" value="jsp,action"/>response) <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>throws <constant name="struts.action.extension" value="jsp,action"/>java.io.IOException, <constant name="struts.action.extension" value="jsp,action"/>javax.servlet.ServletException <constant name="struts.action.extension" value="jsp,action"/>{ <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>final <constant name="struts.action.extension" value="jsp,action"/>java.lang.String <constant name="struts.action.extension" value="jsp,action"/>_jspx_method <constant name="struts.action.extension" value="jsp,action"/>= <constant name="struts.action.extension" value="jsp,action"/>request.getMethod(); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>if <constant name="struts.action.extension" value="jsp,action"/>(!"GET".equals(_jspx_method) <constant name="struts.action.extension" value="jsp,action"/>&& <constant name="struts.action.extension" value="jsp,action"/>!"POST".equals(_jspx_method) <constant name="struts.action.extension" value="jsp,action"/>&& <constant name="struts.action.extension" value="jsp,action"/>!"HEAD".equals(_jspx_method) <constant name="struts.action.extension" value="jsp,action"/>&& <constant name="struts.action.extension" value="jsp,action"/>!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) <constant name="struts.action.extension" value="jsp,action"/>{ <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, <constant name="struts.action.extension" value="jsp,action"/>"JSPs <constant name="struts.action.extension" value="jsp,action"/>only <constant name="struts.action.extension" value="jsp,action"/>permit <constant name="struts.action.extension" value="jsp,action"/>GET <constant name="struts.action.extension" value="jsp,action"/>POST <constant name="struts.action.extension" value="jsp,action"/>or <constant name="struts.action.extension" value="jsp,action"/>HEAD"); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>return; <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>}
复制代码 生成上述代码的实现位于org.apache.jasper.compiler.Generator类中,如下所示- // <constant name="struts.action.extension" value="jsp,action"/>Method <constant name="struts.action.extension" value="jsp,action"/>checkif <constant name="struts.action.extension" value="jsp,action"/>(!pageInfo.isErrorPage()) <constant name="struts.action.extension" value="jsp,action"/>{ <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>out.printil("final <constant name="struts.action.extension" value="jsp,action"/>java.lang.String <constant name="struts.action.extension" value="jsp,action"/>_jspx_method <constant name="struts.action.extension" value="jsp,action"/>= <constant name="struts.action.extension" value="jsp,action"/>request.getMethod();"); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>out.printin("if <constant name="struts.action.extension" value="jsp,action"/>(!"GET".equals(_jspx_method) <constant name="struts.action.extension" value="jsp,action"/>&& <constant name="struts.action.extension" value="jsp,action"/>!"POST".equals(_jspx_method) <constant name="struts.action.extension" value="jsp,action"/>&& <constant name="struts.action.extension" value="jsp,action"/>!"HEAD".equals(_jspx_method) <constant name="struts.action.extension" value="jsp,action"/>&& <constant name="struts.action.extension" value="jsp,action"/>"); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>out.println("!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) <constant name="struts.action.extension" value="jsp,action"/>{"); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>out.pushIndent(); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>out.printin("response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, <constant name="struts.action.extension" value="jsp,action"/>"); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>out.println(""" <constant name="struts.action.extension" value="jsp,action"/>+ <constant name="struts.action.extension" value="jsp,action"/>Localizer.getMessage("jsp.error.servlet.invalid.method") <constant name="struts.action.extension" value="jsp,action"/>+ <constant name="struts.action.extension" value="jsp,action"/>"");"); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>out.printil("return;"); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>out.popIndent(); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>out.printil("}"); <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/> <constant name="struts.action.extension" value="jsp,action"/>out.println();}
复制代码 分析结论
这说明高版本的Tomcat已经意识到前述问题,并做了修复。
但此时还有一事不明,当请求HTTP请求中的方法不正确时,7.0.x版本的Tomcat依然可以正常返回页面信息。由于手上没有平台加固过的Tomcat的源码,这事情只好不了了之。
解决之道
显而易见,最直接的解决方法是更换Tomcat的版本,直接使用官网上发布的9.0.x版本。但官网发布的Tomcat没有经过安全加固,在项目中使用时需要自行做加固,难度不低,工作量不小。
所以不能换版本,得另想办法。
当前的诉求很简单,只允许Web服务器响应GET和POST请求,如果用户发起了其它请求,则清理会话、并跳转至错误页面。聪明的朋友一定想到了,使用J2EE标准中提供的Filter即可满足。
参考资料
关于HTTP方法
其它
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |