[2022虎符]ezchain
代码审计
static class MyHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
String query = t.getRequestURI().getQuery();
Map<String, String> queryMap = queryToMap(query);
String response = "Welcome to HFCTF 2022";
if (queryMap != null) {
String token = queryMap.get("token");
String secret = "HFCTF2022";
if (Objects.hashCode(token) == secret.hashCode() && !secret.equals(token)) {
InputStream is = t.getRequestBody();
try {
Hessian2Input input = new Hessian2Input(is);
input.readObject();
} catch (Exception e) {
response = "oops! something is wrong";
}
} else {
response = "your token is wrong";
}
}
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
if (Objects.hashCode(token) == secret.hashCode() && !secret.equals(token))
这个waf
差点被搞晕
两边的hashCode单步进去不大一样,右边的进去后是String的hashCode
据说直接爆破也可,这里由于知道h=hash=0
解一下密大概是这样:
x0 = 31*0 + 明文[0]
x1 = 31*x0 + 明文[1]
。。。
于是两边同时-1
x0-1 = 31*0 + 明文[0] - 1
代入后面,为了保证还等于x1,后面要+31
x1 = 31*(x0-1 ) + 明文[1] + 31
所以令:
伪造的明文[0] = 明文[0] - 1
伪造的明文[1] + 31 = 明文[1] + 31
可以达到这个效果,即
GeCTF2022
GeCTF2022
这个预期类需要满足几个条件
- 有 readobject
- 有 getter 方法,且无参数
- 继承 Serializable
SignedObject
getObject
它竟然自带了一个反序列化的功能,不可思议
看看它的构造函数
开始测试
Students.java
import java.io.Serializable;
public class Students implements Serializable {
private int age = 11;
private String name ="aaa";
private transient String nickName = "miku";
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
// 强制反序列化 name
this.nickName = "whoami";
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", nick='" + nickName + '\'' +
'}';
}
}
手写利用代码
Students student = new Students();
Students aaa = (Students) signedObject.getObject();//提供序列化功能
System.out.println(aaa);
然后很快发现缺序列化和new signedObject
分析一下
然后就是这俩
PrivateKey signingKey,
Signature signingEngine
但是new的时候会发现这两个一个是接口一个是抽象类,
找了一下signedObject里面有无实现的函数,无果,于是寻求谷歌和神的帮助
这是一种固定用法
神给初学者的建议,这富有哲理,倘若一个人生来就不断地思考我从哪里来要到哪里去的话,它可能就忘记做个正常人了
最终demo
hessain.java
import java.io.*;
import java.lang.reflect.Field;
import java.security.*;
public class hessain {
public static void main(String[] args) throws Exception {
Students student = new Students();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
Signature signature = Signature.getInstance(privateKey.getAlgorithm());
SignedObject signedObject = new SignedObject(student, privateKey, signature);
Students aaa = (Students) signedObject.getObject();
System.out.println(aaa);
}
}
TemplatesImpl.readObject
然后缝合hessian+rome+SignedObjec
之后的涉及二次反序列化完整利用链子+内存马
等学会了再更新