Struts2漏洞利用原理及OGNL机制研究

合集下载

Struts2漏洞利用原理及OGNL机制

Struts2漏洞利用原理及OGNL机制

Struts2漏洞利⽤原理及OGNL机制Struts2漏洞利⽤原理及OGNL机制研究概述在MVC开发框架中,数据会在MVC各个模块中进⾏流转。

⽽这种流转,也就会⾯临⼀些困境,就是由于数据在不同MVC层次中表现出不同的形式和状态⽽造成的:View层—表现为字符串展⽰数据在页⾯上是⼀个扁平的、不带数据类型的字符串,⽆论数据结构有多复杂,数据类型有多丰富,到了展⽰的时候,全都⼀视同仁的成为字符串在页⾯上展现出来。

数据在传递时,任何数据都都被当作字符串或字符串数组来进⾏。

Controller层—表现为java对象在控制层,数据模型遵循java的语法和数据结构,所有的数据载体在Java世界中可以表现为丰富的数据结构和数据类型,你可以⾃⾏定义你喜欢的类,在类与类之间进⾏继承、嵌套。

我们通常会把这种模型称之为复杂的对象树。

数据在传递时,将以对象的形式进⾏。

可以看到,数据在不同的MVC层次上,扮演的⾓⾊和表现形式不同,这是由于HTTP协议与java的⾯向对象性之间的不匹配造成的。

如果数据在页⾯和Java世界中互相传递,就会显得不匹配。

所以也就引出了⼏个需要解决的问题:1.当数据从View层传递到Controller层时,我们应该保证⼀个扁平⽽分散在各处的数据集合能以⼀定的规则设置到Java世界中的对象树中去。

同时,能够灵活的进⾏由字符串类型到Java中各个类型的转化。

2.当数据从Controller层传递到View层时,我们应该保证在View层能够以某些简易的规则对对象树进⾏访问。

同时,在⼀定程度上控制对象树中的数据的显⽰格式。

我们稍微深⼊思考这个问题就会发现,解决数据由于表现形式的不同⽽发⽣流转不匹配的问题对我们来说其实并不陌⽣。

同样的问题会发⽣在Java世界与数据库世界中,⾯对这种对象与关系模型的不匹配,我们采⽤的解决⽅法是使⽤如hibernate,iBatis等框架来处理java对象与关系数据库的匹配。

现在在Web层同样也发⽣了不匹配,所以我们也需要使⽤⼀些⼯具来帮助我们解决问题。

31________struts2_3_ognl_非UI_UI_过滤投影

31________struts2_3_ognl_非UI_UI_过滤投影

OGNL:【struts的标签库在 struts2-core-2.3.11.jar 下的META-INF下】【引入标签库:<%@ taglib uri="/struts-tags" prefix="s"%>】OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。

Struts2框架使用OGNL作为默认的表达式语言。

OGNL相对其它表达式语言具有下面几大优势:1、支持对象方法调用,如xxx.doSomeSpecial();2、支持类静态的方法调用和值访问,表达式的格式:@[类全名(包括包路径)]@[方法名 | ?值名],例如:@ng.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;3、支持赋值操作和表达式串联,如price=100, discount=0.8,calculatePrice(),这个表达式会返回80;4、访问OGNL上下文(OGNL context)和ActionContext;5、操作集合对象。

Ognl 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了java.utils.Map的接口.OGNL(Object Graph Navigation Language),是一种表达式语言。

使用这种表达式语言,你可以通过某种表达式语法,存取Java对象树中的任意属性、调用Java对象树的方法、同时能够自动实现必要的类型转化。

如果我们把表达式看做是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。

================================================================================ ====================================================【一、理解Struts2中的 ValueStack:】ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象.Struts 框架把 ValueStack 对象保存在名为“struts.valueStack”的请求属性中,request 中在 ValueStack 对象的内部有两个逻辑部分:ObjectStack: Struts 把动作和相关对象压入 ObjectStack 中--List 对象栈ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中Map栈Struts 会把下面这些映射压入 ContextMap 中 (Map栈中)root: ObjectStack对象栈的引用parameters: 该 Map 中包含当前请求的请求参数request: 该 Map 中包含当前 request 对象中的所有属性session: 该 Map 中包含当前 session 对象中的所有属性application:该 Map 中包含当前 application 对象中的所有属性attr: 该 Map 按如下顺序来检索某个属性: request, session, application在ObjectStack(对象栈)中一般放入:ValueStackAction对象map集合实体类对象================================================================================ =======================================【二、理解OGNL Context】OgnlValueStack 类包含两个重要的属性一个root和一个context。

Struts2系列漏洞起始篇

Struts2系列漏洞起始篇

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开始分析。

ognl注入原理

ognl注入原理

ognl注入原理OGNL(Object-Graph Navigation Language)是一种用于Java编程语言的表达式语言,它可以用于访问和操作对象图。

OGNL注入是一种常见的Web应用程序漏洞,它允许攻击者通过构造恶意输入来执行任意代码。

OGNL注入的原理是利用Web应用程序中对用户输入的不正确处理。

当应用程序接收到用户输入并将其用作OGNL表达式的一部分时,如果没有正确地验证和过滤用户输入,攻击者可以构造恶意输入来执行任意代码。

攻击者可以通过在用户输入中插入OGNL表达式来利用OGNL注入漏洞。

这些表达式可以执行任意的Java代码,包括读取、修改或删除应用程序中的数据,甚至执行系统命令。

为了防止OGNL注入漏洞,开发人员应该采取以下措施:1. 输入验证和过滤:开发人员应该对用户输入进行严格的验证和过滤,确保只允许预期的输入。

可以使用正则表达式或白名单来限制输入的内容。

2. 输入转义:开发人员应该对用户输入进行适当的转义,以确保输入不会被解释为OGNL表达式。

可以使用特殊字符转义函数或库来实现。

3. 最小权限原则:应用程序应该以最小权限原则运行,即只给予应用程序所需的最低权限。

这样即使攻击者成功执行了OGNL注入,也只能在应用程序的权限范围内进行操作。

4. 安全配置:开发人员应该对应用程序的安全配置进行审查和优化。

例如,禁用不必要的OGNL功能或限制OGNL表达式的使用范围。

5. 安全更新:开发人员应该及时更新和修补应用程序中使用的框架和库,以确保及时修复已知的OGNL注入漏洞。

总之,OGNL注入是一种常见的Web应用程序漏洞,攻击者可以利用它执行任意代码。

为了防止OGNL注入漏洞,开发人员应该对用户输入进行严格的验证和过滤,进行适当的输入转义,以及采取最小权限原则和安全配置。

及时更新和修补应用程序中使用的框架和库也是非常重要的。

只有这样,我们才能有效地保护Web应用程序免受OGNL注入攻击的威胁。

Struts2远程代码执行漏洞(S2-046)漏洞复现

Struts2远程代码执行漏洞(S2-046)漏洞复现

Struts2远程代码执行漏洞(S2-046)漏洞复现漏洞复现继 3 月 7 日爆发的 S2-045 远程命令执行漏洞风波之后,今日 Struts2 官方发布另一个高危漏洞S2-046,CVE 编号依然是CVE-2017-5638,据官方披露,最新的漏洞与 S2-045 类似,只是攻击字段发生变化。

修复方案依然与S2-045 相同,升级至2.3.32 或者2.5.10.1 版本即可防御针对这两个漏洞攻击。

S2-046Struts2 是一个基于MVC 设计模式的Web 应用框架,它本质上相当于一个 servlet,在MVC 设计模式中,Struts2 作为控制器(Controller) 来建立模型与视图的数据交互。

Struts2 的使用范围及其广泛,国内外均有大量厂商使用该框架。

漏洞描述:据漏洞提交者纰漏,S2-046 的利用条件有以下三个方面:1、系统必须使用Jakarta 插件,检查Struts2 配置文件中是否有以下配置:<constant name =“struts.multipart.parser”value =“jakarta-stream”/>2、上传文件的大小(由Content-LSength 头指定)大于Struts2 允许的最大大小(2GB)3、文件名内容构造恶意的 OGNL 内容。

如果满足以上要求,Struts2 受影响版本将创建一个包含攻击者控制的异常文件名,使用 OGNL 值堆栈来定位错误消息,OGNL 值堆栈将插入任何 OGNL 变量($ {}或%{})作为 OGNL 表达式,然后实现任意代码执行。

目前网络上已披露出针对 S2-046 的 POC漏洞复现:我们在本地搭建环境进行测试:查看 Struts2 的配置文件,发现存在<constant name =“struts.multipart.parser”value =“jakarta-stream”/>Struts2 的配置文件下面进行网站上传测试,构造数据包如下,设定Content-LSength 值大于 2GB,并构造恶意文件名,如下图所示:构造数据包通过响应数据包可看到恶意代码成功执行,攻击成功,如下图所示:代码成功执行。

Struts2S2-020漏洞介绍

Struts2S2-020漏洞介绍

Struts2 S2-020漏洞简介1.漏洞概述今年二月初,Apache Tomcat项目组委员会成员Mark Thomas提到CVE-2014-0050漏洞本是通过JPCERT上报给Apache软件基金会,但是由于处理邮件失误,导致漏洞细节泄露,使得这个问题提前曝光。

随后在三月,Apache 官方公布了S2-020漏洞公告,公告里简要描述了该漏洞形成的原因和临时解决方案。

在官方这个通告公布的一段时间后,各大厂商已经采取了相应的安全措施去解决或预防这个漏洞。

但在不久之后,在SecurityFocus、Spiderlabs等安全网站上又披露了CVE-2014-0094漏洞修补方案本身存在漏洞,导致补丁被完全绕过,造成更大的危害。

近日,官方在GitHub上已经对该问题做出了修正,但随后发现该修正方案也可绕过。

2.漏洞危害官方在S2-020漏洞公告里介绍了两种漏洞(CVE-2014-0050、CVE-2014-0094):一是通过Commons-fileupload造成的拒绝服务攻击;另一个是附加的ParametersInterceptor允许访问'class' 参数(该参数直接映射到getClass()函数),并允许控制ClassLoader。

例如,给当前应用目录赋值地址映射目录是攻击者可控的目录时,攻击者便可轻易地执行预先设置好的代码;另一个危害是给当前应用目录赋值一个不存在的地址(class.classLoader.resources.dirContext.docBase=不存在路径)会导致应用404,这样当前应用,以后不管访问哪个地址都是404了(因为映射的目录不存在),造成DoS效果。

近日安全研究人员发现Apache Struts2 S2-020,在CVE-2014-0094的漏洞修补方案中存在漏洞,漏洞补丁存在被绕过的风险,可能导致执行任意代码。

3.解决方案官方解决方案:升级struts版本到2.3.16.1。

Struts S2-045 漏洞调试及分析

Struts S2-045 漏洞调试及分析

Struts S2-045漏洞调试及分析Auth:Cryin’Date:2016.3.9漏洞公告首先看官方给出的漏洞公告信息:“Possible Remote Code Execution when performing file upload based on Jakarta Multipart parser.”问题原因:“It is possible to perform a RCE attack with a malicious Content-Type value. If the Content-Type value isn't valid an exception is thrown which is then used to display an error message to a user.”从公告信息可以得到几个漏洞的重点信息:●存在漏洞的模块是Jakarta●漏洞产生的点是恶意的Content-Type头●恶意的Content-Type头会造成程序抛出异常,在显示错误消息给用户时造成RCE 补丁对比查看Struts2版本2.3.32在github上的commit(Uses default error key if specified key doesn't exist)并对比修改内容:https:///apache/struts/commit/352306493971e7d5a756d61780d57a76eb1 f519a可以看到对LocalizedTextUtil.findText方法进行了重写,并添加了判断。

Struts2RCE漏洞的根本原因是程序将用户可控数据带入OGNL表达式解析并执行,而OGNL(Object Graph Navigation Language)对象图形导航语言是一个功能强大的表达式语言,可以用来获取和设置Java对象的属性,但同时也可以对服务端对象进行修改,绕过沙盒甚至可以执行系统命令。

Struts-S2-045漏洞利用

Struts-S2-045漏洞利用

Struts-S2-045漏洞利⽤最近也是在看Struts2的漏洞,这⾥与⼤家共同探讨⼀下,本次我复现的是s2-045这个编号的漏洞漏洞介绍Apache Struts 2被曝存在远程命令执⾏漏洞,漏洞编号S2-045,CVE编号CVE-2017-5638,在使⽤基于Jakarta插件的⽂件上传功能时,有可能存在远程命令执⾏,导致系统被⿊客⼊侵。

恶意⽤户可在上传⽂件时通过修改HTTP请求头中的Content-Type值来触发该漏洞,进⽽执⾏系统命令。

Struts2是⼀个基于MVC设计模式的Web应⽤框架,它本质上相当于⼀个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建⽴模型与视图的数据交互。

Struts2框架存在多个远程代码执⾏(S2-005、S2-009、S2-013、S2-016、S2-019、S2-020、S2-037、devmode),恶意攻击者可利⽤漏洞直接获取应⽤系统的Webshell,甚⾄获取操作系统以及数据库的权限。

漏洞编号:S2-045CVE编号:CVE-2017-5638漏洞类型:远程代码执⾏漏洞级别:⾼危漏洞风险:⿊客通过利⽤漏洞可以实现远程命令执⾏。

影响版本:struts2.3.5 – struts2.3.31 , struts2.5 – struts2.5.10环境准备1.docker环境及vulhub靶场(没有安装的可以参考我之前的博客)2.Burp Suite抓包⼯具漏洞POCContent-Type:"%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@ng.System@getProperty('').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new ng.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@mons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"漏洞关键点1.基于Jakarta(Jakarta Multipart parser)插件的⽂件上传功能2.恶意攻击者精⼼构造Content-Type的值通过版本⽐对定位漏洞原因:1.coresrcmainjavaorgapachestruts2dispatchermultipartMultiPartRequestWrapper.java2.coresrcmainjavaorgapachestruts2dispatchermultipartJakartaMultiPartRequest.java3.coresrcmainjavaorgapachestruts2dispatchermultipartJakartaStreamMultiPartRequest.java三个⽂件修改内容相同,加固⽅式对⽤户报错加了条件判断。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Struts2漏洞利用原理及OGNL机制研究Auth:Cryin’Date:2015.04.19概述在MVC开发框架中,数据会在MVC各个模块中进行流转。

而这种流转,也就会面临一些困境,就是由于数据在不同MVC层次中表现出不同的形式和状态而造成的:◆View层—表现为字符串展示数据在页面上是一个扁平的、不带数据类型的字符串,无论数据结构有多复杂,数据类型有多丰富,到了展示的时候,全都一视同仁的成为字符串在页面上展现出来。

数据在传递时,任何数据都都被当作字符串或字符串数组来进行。

◆Controller层—表现为java对象在控制层,数据模型遵循java的语法和数据结构,所有的数据载体在Java世界中可以表现为丰富的数据结构和数据类型,你可以自行定义你喜欢的类,在类与类之间进行继承、嵌套。

我们通常会把这种模型称之为复杂的对象树。

数据在传递时,将以对象的形式进行。

可以看到,数据在不同的MVC层次上,扮演的角色和表现形式不同,这是由于HTTP协议与java的面向对象性之间的不匹配造成的。

如果数据在页面和Java世界中互相传递,就会显得不匹配。

所以也就引出了几个需要解决的问题:1.当数据从View层传递到Controller层时,我们应该保证一个扁平而分散在各处的数据集合能以一定的规则设置到Java世界中的对象树中去。

同时,能够灵活的进行由字符串类型到Java中各个类型的转化。

2.当数据从Controller层传递到View层时,我们应该保证在View层能够以某些简易的规则对对象树进行访问。

同时,在一定程度上控制对象树中的数据的显示格式。

我们稍微深入思考这个问题就会发现,解决数据由于表现形式的不同而发生流转不匹配的问题对我们来说其实并不陌生。

同样的问题会发生在Java世界与数据库世界中,面对这种对象与关系模型的不匹配,我们采用的解决方法是使用如hibernate,iBatis等框架来处理java对象与关系数据库的匹配。

现在在Web层同样也发生了不匹配,所以我们也需要使用一些工具来帮助我们解决问题。

为了解决数据从View层传递到Controller层时的不匹配性,Struts2采纳了XWork的一套完美方案。

并且在此的基础上,构建了一个完美的机制,从而比较完美的解决了数据流转中的不匹配性。

就是表达式引擎OGNL。

它的作用就是帮助我们完成这种规则化的表达式与java对象的互相转化(以上内容参考自Struts2技术内幕)。

关于OGNLOGNL(Object Graph Navigation Language)即对象图形导航语言,是一个开源的表达式引擎。

使用OGNL,你可以通过某种表达式语法,存取Java对象树中的任意属性、调用Java 对象树的方法、同时能够自动实现必要的类型转化。

如果我们把表达式看做是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。

我们可以轻松解决在数据流转过程中所遇到的各种问题。

OGNL进行对象存取操作的API在Ognl.java文件中,分别是getValue、setValue两个方法。

getValue通过传入的OGNL表达式,在给定的上下文环境中,从root对象里取值:setValue通过传入的OGNL表达式,在给定的上下文环境中,往root对象里写值:OGNL同时编写了许多其它的方法来实现相同的功能,详细可参考Ognl.java代码。

OGNL的API很简单,无论何种复杂的功能,OGNL会将其最终映射到OGNL的三要素中通过调用底层引擎完成计算,OGNL的三要素即上述方法的三个参数expression、root、context。

OGNL三要素◆Expression(表达式):Expression规定OGNL要做什么,其本质是一个带有语法含义的字符串,这个字符串将规定操作的类型和操作的内容。

OGNL支持的语法非常强大,从对象属性、方法的访问到简单计算,甚至支持复杂的lambda表达式。

◆Root(根对象):OGNL的root对象可以理解为OGNL要操作的对象,表达式规定OGNL要干什么,root 则指定对谁进行操作。

OGNL的root对象实际上是一个java对象,是所有OGNL操作的实际载体。

◆Context(上下文):有了表达式和根对象,已经可以使用OGNL的基本功能了。

例如,根据表达式对root 对象进行getvalue、setvalue操作。

不过事实上在OGNL内部,所有的操作都会在一个特定的数据环境中运行,这个数据环境就是OGNL的上下文。

简单说就是上下文将规定OGNL的操作在哪里进行。

OGNL的上下文环境是一个MAP结构,定义为OgnlContext,root对象也会被添加到上下文环境中,作为一个特殊的变量进行处理。

OGNL基本操作◆对root对象的访问:针对OGNL的root对象的对象树的访问是通过使用‘点号’将对象的引用串联起来实现的。

通过这种方式,OGNL实际上将一个树形的对象结构转化为一个链式结构的字符串来表达语义,如下://获取root对象中的name属性值name//获取root对象department属性中的name属性值//获取root对象department属性中的manager属性中的name属性值◆对上下文环境的访问:Context上下文是一个map结构,访问上下文参数时需要通过#符号加上链式表达式来进行,从而表示与访问root对象的区别,如下://获取上下文环境中名为introduction的对象的值#introduction//获取上下文环境中名为parameters的对象中的user对象中名为name属性的值#◆对静态变量、方法的访问:在OGNL中,对于静态变量、方法的访问通过@[class]@[field/method]访问,这里的类名要带着包名。

如下//访问com.example.core.Resource类中名为img的属性值@com.example.core.Resource@img//调用com.example.core.Resource类中名为get的方法@com.example.core.Resource@get()◆访问调用://调用root对象中的group属性中users的size()方法ers.size()//调用root对象中group中的containsUser方法,并传递上下文环境中名为user值作为参数group.containsUser(#user)◆构造对象OGNL支持直接通过表达式来构造对象,构造的方式主要包括三种:1.构造List:使用{},中间使用逗号隔开元素的方式表达列表2.构造map:使用#{},中间使用逗号隔开键值对,并使用冒号隔开key和value3.构造对象:直接使用已知的对象构造函数来构造对象可以看到OGNL在语法层面上所表现出来的强大之处,不仅能够直接对容器对象构造提供语法层面支持,还能够对任意java对象提供支持。

然而正因为OGNL过于强大,它也造成了诸多安全问题。

恶意攻击者通过构造特定数据带入OGNL表达式解析并执行,而OGNL可以用来获取和设置Java对象的属性,同时也可以对服务端对象进行修改,所以只要绕过沙盒恶意攻击者甚至可以执行系统命令进行系统攻击。

深入OGNL实现类在OGNL三要素中,context上下文环境为OGNL提供计算运行的环境,这个运行环境在OGNL内部由OgnlContext类实现,它是一个map结构。

在OGNL.java中可以看到OgnlContext 会在OGNL计算时动态创建,同时传入map结构的context,并根据传入的参数设定OGNL 计算的一些默认行为以及设置root对象。

这里看到MemberAccess属性,在struts2漏洞利用中经常看到。

转到OgnlContext类中查看。

MemberAccess指定OGNL的对象属性、方法访问策略,这里初始默认情况下是flase,即默认不允许访问。

在struts2中SecurityMemberAccess类封装了DefaultMeberAccess类并进行了扩展,指定是否支持访问静态方法以及通过指定正则表达式来规定某些属性是否能够被访问。

其中allowStaticMethodAccess默认为flase,即默认禁止访问静态方法。

另外在OGNL实现了MethodAccessor及PropertyAccessor类规定OGNL在访问方法和属性时的实现方式,详细可参考代码文件。

在struts2中,XWorkMethodAccessor类对MethodAccessor进行了封装,其中在callStaticMethod方法中可以看到,程序首先从上下文获取到DENY_METHOD_EXECUTION值并转换为布尔型,如果为false则可以执行静态方法,如果为true则不执行静态发放并返回null。

Struts2漏洞利用原理上文已经详细介绍了OGNL引擎,因为OGNL过于强大,它也造成了诸多安全问题。

恶意攻击者通过构造特定数据带入OGNL表达式即可能被解析并执行,而OGNL可以用来获取和设置Java对象的属性,同时也可以对服务端对象进行修改,所以只要绕过Struts2的一些安全策略,恶意攻击者甚至可以执行系统命令进行系统攻击。

如struts2远程代码执行漏洞s2-005。

XWork通过getters/setters方法从HTTP的参数中获取对应action的名称,这个过程是基于OGNL的。

OGNL是怎么处理的呢?如下:user.address.city=Bishkek&user['favoriteDrink']=kumys会被转化成:action.getUser().getAddress().setCity("Bishkek")action.getUser().setFavoriteDrink("kumys")这个过程是由ParametersInterceptor调用ValueStack.setValue()完成的,它的参数是用户可控的,由HTTP参数传入。

虽然Struts2出于安全考虑,在SecurityMemberAccess类中通过设置禁止静态方法访问及默认禁止执行静态方法来阻止代码执行。

即上面提及的denyMethodExecution为true,MemberAccess为false。

但这两个属性都可以被修改从而绕过安全限制执行任意命令。

POC如下:http://mydomain/MyStruts.action?('\u0023_memberAccess[\'allowStaticMethodAccess\']')( meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u00 23foo')(\u0023foo\u003dnew%ng.Boolean("false")))&(asdf)(('\u0023rt.exec(‘ipconfig’)') (\u0023rt\u003d@ng.Runtime@getRuntime()))=1在POC中\u0023是因为S2-003对#号进行了过滤,但没有考虑到unicode编码情况,而通过#_memberAccess[\'allowStaticMethodAccess\']')(meh)=true,可以设置允许访问静态方法,因为getRuntime方法是静态的,通过context[\'xwork.MethodAccessor.denyMethodExecution\']=#foo')(\#foo=new%ng.Boole an("false")设置拒绝执行方法为false,也就是允许执行静态方法。

相关文档
最新文档