Struts2系列漏洞起始篇
前言
到目前位置struts2的漏洞编号已经到了S2-057,一直想系统的学习下Struts2的漏洞,但由于工作量较大,一直搁浅。最近由于工作需要,借此机会来填下坑。个人认为一个框架漏洞出来了仅仅看下别人分析的文章是远远不够,因为这些文章往往都只针对个别漏洞,可能框架中还存在类似的漏洞你依然发现不了。所以我说需要系统的学习下,从框架的源码开始分析它的工作流程(当然这里我会有所取舍,全部都讲没意义),同时这样也会加深自己对该框架的理解,之后如果一个新的漏洞出来了,你可以仅根据官方的公告或变动的代码很简单地还原整个漏洞,同时这样做对代码审计也会有一定的帮助。这是我struts2系列文章的第一篇,篇幅会比较长(实际上分析源码的地方我已经省了很多)。之后我还会写spring、tomcat等系列的漏洞分析文章。
准备工作
我使用的是eclipse+struts-core2.1.6,struts2的各版本是由些许区别的,但是大致流程都是相同的,这里采用较老的版本是因为S2早期的漏洞都可以在里面找到,方便分析。
Struts2的工作流程
在原生的jsp+servlet项目中,常用会到Filter过滤器来过滤一些参数等等,这里struts2就是将自己的核心过滤器配置在web.xml中,这样可以让指定的HTTP请求都经过Struts2。早期struts2的核心过滤器是FilterDispathcer (org.apache.struts2.dispatcher.FilterDispatcher),但是struts2>=2.1.3之后就变为了StrutsPrepareAndExecuteFilter,而StrutsPrepareAndExecuteFilter在配置的时候也经常会分开为StrutsPrepareFilter和StrutsExecuteFilter,这是方便开发者更加灵活的使用,配置信息如下:

Filter的执行顺序是然配置顺序来的,所以这里我们先从StrutsPrepareFilter开始分析。

一个Filter比较重要的两个方法,一个是init一个doFilter,init是Filter初始化的时候才会调用,一般是容器刚启动时,而传入的参数FilterConfig实际上就是对应web.xml中的Filter配置信息,doFilter方法是一个Filter功能实现的核心。Filter处理StrutsPrepareFilter的init方法主要是初始化dispatcher,这是由于dispatcher是一个非常重要的类,但是由于如果详细解释dispatcher比较麻烦,大家有兴趣可以自行了解。
这里主要分析doFilter方法,59行处调用了工具类PrepareOperations的createActionContext创建一个action的上下文。

由于是第一次,所以会进入到else分支中,74行处通过工厂模式创建了一个ValueStack(值栈),大家到这里debug一下就知道这里创建的实例实际上是一个OgnlValueStack对象,而它就是Struts2的ognl表达式注入的元凶(后面我们分析漏洞的时候再进入该类中看下源码)。随后又将request对象、response对象以及servlet上下文放入了OgnlValueStack中的Context属性(一个map),并用该Context又创建了action上下文并返回。
回到StrutsPrepareFilter的doFilter方法中,assignDispatcherToThread将当前dispatcher放入到当前本地线程中,setEncodingAndLocale用于设置请求的本地化,语言以及编码格式,不用管。需要注意的是wrapRequest方法,该方法根据请求类型的不同,采用不同的request包装类,当为'multipart/form-data'时代表文件下载,将使用JakartaMultiPartRequest类,此类与S2-045有关,我们之后的文章再详细分析。findActionMapping方法用于构建action的映射类,最后调用do.Filter进入到下一个过滤器(这里是StrutsExecuteFilter)。

更进findActionMapping函数:

同样的,大家在184行处debug一下就知道了这里调用的是DefaultActionMapper的getMpping方法,跟进:

该方法内就是通过uri来解析对应的action配置信息,例如namespace、actionname、method。parseNameAndNamespace方法根据uri和配置文件中的namespace进行对比来判断namespace,S2-057漏洞就和该函数相关(后面的文章分析)。handleSpecialParameters是struts2识别请求url后的特殊参数然后做一些特殊做处理,S2-016、S2-017、S2-018都与此函数相关。会识别如下四种特殊字符:

parseActionName方法用于,当项目开启了动态方法调用时,也就是struts.xml配置了常量<constant name="struts.enable.DynamicMethodInvocation" value="true" />时,识别 !后面字符串作为action的method。
到这里StrutsPrepareFilter就分析完了,主要工作有两点:一是为struts2执行做一些相关的准备,如加载相关的配置信息。二是为struts2的request请求处理相关的信息。
接下来到了StrutsExecuteFilter,该拦截器才是真正执行action请求的,进入doFilter方法:

跟进executeAction发现实际上是调用了Dispatcher.serviceAction,这里直接跟进serviceAction就好了:

值得注意的是如果此时的mapping中已经有了Result说明该请求时直接访问的页面,将会进入if分支,执行StrutsResultSupport.execute方法,关于这个方法,我们后面会讲到。
StrutsActionProxy的execute方法中实际上又是通过调用了DefaultActionInvocation的invoke来执行action的

也就是说Dispatcher类是重要的调结者,而DefaultActionInvocation类才是执行action类实例的行动者。action代理类(ActionProxy类)则是他们之间的中间人。相当于Dispatcher类通过action代理类(ActionProxy类)命令DefaultActionInvocation类去执行action类实例。跟进DefaultActionInvocation的invoke方法:

struts2自动的默认拦截器中也存在很多问题,不仅只有S2-019,还有S2-020(ParametersInterceptor)、S2-021(ParametersInterceptor)、S2-022(CookieInterceptor)
跟进invokeActionOnly中又通过调用了invokeAction,跟进invokeAction:


大家可以看到invokeAction中才是真正执行action的地方,不过由于版本的不同,高版本中该函数内并不是通过反射机制而是ognl表达式来的执行的action。执行完action中的方法后将会返回一个Result对象。Result对象就是将mvc模式中controller层和view层连接起来的地方。
回到DefaultActionInvocation的invoke方法中,执行完action后就是操作返回的result了。

跟进executeResult方法:

createResult()就是我们之前说的,执行完action后如果返回的是字符串,需要去配置文件(struts.xml)中找对应的Result类型,如果没有设置type默认是dispatcher,对应着的Result类是org.apache.struts2.result.ServletDispatcherResult。所有的Result类都会继承StrutsResultSupport类,这里execute方法时父类StrutsResultSupport的(前面提到过这个),跟进:

1.conditionalParse用于处理房前的location,也就是跳转地址,里面会判断location是否有ognl表达式,有的话将会执行表达式,也是因为可能是动态返回结果。我们后面分析漏洞时后详细介绍该函数。
2.接着就是调用StrutsResultSupport子类的doExecute了。
Struts2自带多个Result类型,在struts-default.xml中可以看到

strut2的部分漏洞也是和他们相关的,比如说S2-031就和xslt这个返回类型有关。
这里我们只进入ServletDispatcherResult类中的doExecute看看

里面的内容比较简单,大概就是通过请求转发到下一个servlet(jsp本身就是一个servlet)。到这里struts2的基本工作流程就分析完了
参考文章:
https://www.cnblogs.com/hayasi/category/869760.html
https://cwiki.apache.org/confluence/display/WW/Security+Bulletins
Struts2系列漏洞起始篇的更多相关文章
- 【中间件】Struts2系列漏洞POC小结
#Struts2-045 ''' CVE-2017-5638 影响范围:Struts 2.3.5 – Struts 2.3.31,Struts 2.5 – Struts 2.5.10 触发条件:基于J ...
- 程序世界系列之-struts2安全漏洞引发的安全杂谈(上)
目录: 1.讨论关于struts 安全问题. 2.黑客文化. 3.如何降低安全漏洞的出现. 4.忠告建议. 题记: 这篇文章本来很早应该和大家见面的,中间由于个人原因调整了系列文章发布时间,实属罪过. ...
- margin系列之内秀篇(二)
本系列摘自 飘零雾雨的博客 可挖掘性 之前已经写过一篇关于 margin 应用场景的文章:margin系列之内秀篇,当然,它的应用场景会远大于文中所述,无法一一列举. 所以本篇权当是对此的补遗好了, ...
- 跟Google学习Android开发-起始篇-构建你的第一个应用程序(4)
说明:此系列教程翻译自Google Android开发者官网的Training教程,利用Chome浏览器的自动翻译功能作初译,然后在一些语句不顺或容易造成误解的地方作局部修正.方便英文不好的开发者查看 ...
- 【SSH框架】之Struts2系列(二)
微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联 1.Struts2常量配置 (1).Struts2默认常量配置文件路径,如下图: (2).Strut ...
- 【SSH框架】之Struts2系列(一)
微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联系 1.Struts2框架概述 (1).什么是Struts2 Struts2是一种基于MVC模式的轻量 ...
- Mysql高手系列 - 第10篇:常用的几十个函数详解,收藏慢慢看
这是Mysql系列第10篇. 环境:mysql5.7.25,cmd命令中进行演示. MySQL 数值型函数 函数名称 作 用 abs 求绝对值 sqrt 求二次方根 mod 求余数 ceil 和 ce ...
- Mysql高手系列 - 第24篇:如何正确的使用索引?【高手进阶】
Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能. 欢迎大家加我微信itsoku一起交流java.算法.数据库相关技术. 这是Mysql系列第24篇. 学习索引,主要是 ...
- javascript面向对象系列第三篇——实现继承的3种形式
× 目录 [1]原型继承 [2]伪类继承 [3]组合继承 前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.本文是javascript面向对象系列第三篇——实现继承的3种形式 [ ...
随机推荐
- tensorflow cpu问题
返回: -- ::] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 ...
- Flutter 中使用Future消除Callback Hell
/先分别定义各个异步任务 Future<String> login(String userName, String pwd){ ... //用户登录 }; Future<String ...
- 阶段5 3.微服务项目【学成在线】_day18 用户授权_07-动态查询用户权限-权限数据模型
3 动态查询用户权限 3.1 需求分析 截至目前在测试授权时使用的权限数据是静态数据,正常情况的流程是: 1.管理员给用户分配权限,权限数据写到数据库中. 2.认证服务在进行用户认证时从数据库读取用户 ...
- 清空表且id为0
sql命令: 用于清空某表的数据 且让自增的id重新从0开始 truncate table
- python调用HTMLTestRunner+unittest实现一次执行多个测试类,并生成与每个测试类对应的测试报告,具体看代码,附上整个project代码
python自动化框架雏形,根据自己需要封装:ui自动化,接口自动化均可适用,python版本为python3.x,不要问我为什么不用python2.x,附上整个project代码:http://fi ...
- PAT 甲级 1044 Shopping in Mars (25 分)(滑动窗口,尺取法,也可二分)
1044 Shopping in Mars (25 分) Shopping in Mars is quite a different experience. The Mars people pay ...
- PAT 甲级 1037 Magic Coupon (25 分) (较简单,贪心)
1037 Magic Coupon (25 分) The magic shop in Mars is offering some magic coupons. Each coupon has an ...
- 01.轮播图之二 :tableView 轮播
在做这个tablevew轮播的时候,重要的就是修改frame 和view 的翻转了:::: 也是不难的,概要的设计和scroll 轮播是一致的: 首先是 .h 的文件 @interface Table ...
- redcon, Redis兼容的服务器框架
源代码名称:redcon 源代码网址:http://www.github.com/tidwall/redcon redcon源代码文档 redcon源代码下载 Git URL: 复制代码 git:// ...
- react做的简单的购物车
###第一步 :首先电脑上已经安装react的脚手架 cnpm install create-react-app -g ###第二步 :创建项目 creact-react-app 项目 ...