前言

到目前位置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系列漏洞起始篇的更多相关文章

  1. 【中间件】Struts2系列漏洞POC小结

    #Struts2-045 ''' CVE-2017-5638 影响范围:Struts 2.3.5 – Struts 2.3.31,Struts 2.5 – Struts 2.5.10 触发条件:基于J ...

  2. 程序世界系列之-struts2安全漏洞引发的安全杂谈(上)

    目录: 1.讨论关于struts 安全问题. 2.黑客文化. 3.如何降低安全漏洞的出现. 4.忠告建议. 题记: 这篇文章本来很早应该和大家见面的,中间由于个人原因调整了系列文章发布时间,实属罪过. ...

  3. margin系列之内秀篇(二)

    本系列摘自  飘零雾雨的博客 可挖掘性 之前已经写过一篇关于 margin 应用场景的文章:margin系列之内秀篇,当然,它的应用场景会远大于文中所述,无法一一列举. 所以本篇权当是对此的补遗好了, ...

  4. 跟Google学习Android开发-起始篇-构建你的第一个应用程序(4)

    说明:此系列教程翻译自Google Android开发者官网的Training教程,利用Chome浏览器的自动翻译功能作初译,然后在一些语句不顺或容易造成误解的地方作局部修正.方便英文不好的开发者查看 ...

  5. 【SSH框架】之Struts2系列(二)

    微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联 1.Struts2常量配置 (1).Struts2默认常量配置文件路径,如下图: (2).Strut ...

  6. 【SSH框架】之Struts2系列(一)

    微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联系 1.Struts2框架概述 (1).什么是Struts2 Struts2是一种基于MVC模式的轻量 ...

  7. Mysql高手系列 - 第10篇:常用的几十个函数详解,收藏慢慢看

    这是Mysql系列第10篇. 环境:mysql5.7.25,cmd命令中进行演示. MySQL 数值型函数 函数名称 作 用 abs 求绝对值 sqrt 求二次方根 mod 求余数 ceil 和 ce ...

  8. Mysql高手系列 - 第24篇:如何正确的使用索引?【高手进阶】

    Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能. 欢迎大家加我微信itsoku一起交流java.算法.数据库相关技术. 这是Mysql系列第24篇. 学习索引,主要是 ...

  9. javascript面向对象系列第三篇——实现继承的3种形式

    × 目录 [1]原型继承 [2]伪类继承 [3]组合继承 前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.本文是javascript面向对象系列第三篇——实现继承的3种形式 [ ...

随机推荐

  1. tensorflow cpu问题

    返回: -- ::] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 ...

  2. Flutter 中使用Future消除Callback Hell

    /先分别定义各个异步任务 Future<String> login(String userName, String pwd){ ... //用户登录 }; Future<String ...

  3. 阶段5 3.微服务项目【学成在线】_day18 用户授权_07-动态查询用户权限-权限数据模型

    3 动态查询用户权限 3.1 需求分析 截至目前在测试授权时使用的权限数据是静态数据,正常情况的流程是: 1.管理员给用户分配权限,权限数据写到数据库中. 2.认证服务在进行用户认证时从数据库读取用户 ...

  4. 清空表且id为0

    sql命令: 用于清空某表的数据 且让自增的id重新从0开始 truncate table

  5. python调用HTMLTestRunner+unittest实现一次执行多个测试类,并生成与每个测试类对应的测试报告,具体看代码,附上整个project代码

    python自动化框架雏形,根据自己需要封装:ui自动化,接口自动化均可适用,python版本为python3.x,不要问我为什么不用python2.x,附上整个project代码:http://fi ...

  6. PAT 甲级 1044 Shopping in Mars (25 分)(滑动窗口,尺取法,也可二分)

    1044 Shopping in Mars (25 分)   Shopping in Mars is quite a different experience. The Mars people pay ...

  7. PAT 甲级 1037 Magic Coupon (25 分) (较简单,贪心)

    1037 Magic Coupon (25 分)   The magic shop in Mars is offering some magic coupons. Each coupon has an ...

  8. 01.轮播图之二 :tableView 轮播

    在做这个tablevew轮播的时候,重要的就是修改frame 和view 的翻转了:::: 也是不难的,概要的设计和scroll 轮播是一致的: 首先是 .h 的文件 @interface Table ...

  9. redcon, Redis兼容的服务器框架

    源代码名称:redcon 源代码网址:http://www.github.com/tidwall/redcon redcon源代码文档 redcon源代码下载 Git URL: 复制代码 git:// ...

  10. react做的简单的购物车

    ###第一步 :首先电脑上已经安装react的脚手架 cnpm  install    create-react-app   -g ###第二步 :创建项目 creact-react-app   项目 ...