原文来自:https://bugs.chromium.org/p/chromium/issues/detail?id=788936
翻译:聂心明
来自file:///的资源没有定义一个Content-Type,一个恶意页面将加载任何本地资源作为css,并且它独立于MIME类型,浏览器会将其进行解析。他允许通过css注入的方式来跨域泄露本地文件数据。这个是这个漏洞 https://bugs.chromium.org/p/chromium/issues/detail?id=419383 的小变体。
chrome浏览器似乎用文件拓展名作为MIME类型,当怀疑解析了一个错误的资源的时候,就会弹出一个警告:“资源被解析成样式表,但是被传输的MIME类型是text/html”,这个警告暗示避免使用file:/// 去探测主机文件。

漏洞详细

攻击需要一个受害者打开一个本地恶意的HTML页面。我不在这里讨论怎么做到这点,但是有很多方法可以欺骗用户(强制下载,从本地PDF中跳转,邮件附件……),未来,我猜会在安卓或者其他的特殊电子产品中会更加有用。
在这个文章中我只展示三个POC,完成攻击只需要两个条件

不幸的是,多数情况下,特殊字符会截断css的解析,并且似乎不能泄露整改cookie……,我试图用UTF-16来解决这个问题,但是,令我失望的是,cookie不支持空字符
比较明显的解决方法是,设置cookie为一个有效的值(可打印的ascii字符,分号,等号,引号),当cookie被编码之后,会产生我们期望得到的payload。让我们用神奇的POC吧 !!

cookie是被128-aes加密的,加密模式采用CBC,aes的IV是固定的为,IV = 0x20202020202020202020202020202020。在Linux中,key是被硬编码的2并且,对于key的推导,它使用单次迭代的PBKDF2加密方式,并且salt也是固定的("saltysalt")。在OSX中,key只会被保存在Keychain中。所以我们就把精力放在Linux中。
事实证明,我们的payload"{}*{--:("其实只有8个字节的长度。这就意味着如果我们用UTF-16编码的话,就会产生16个字节的长度(8 + 8 NULL bytes)[3]。
下图(payload,key和iv都是已知的并且是固定值)

我们要找到一个有效的块B,它解码之后满足:

幸亏的是,B0和B2是独立的。在一两分钟之后(在Skylake的i5的电脑上经过至少十亿次aes计算),我们得到一个有效的cookie值,这个cookie被编码之后可以被存储到db中,这个cookie也包含UTF-16格式的payload。

document.cookie="whatever=i+GW*e@afGR]sYo{Wa>7[[[[[[[[[[[[xBLGWAJ|VCX<T*P;"

(你可以通过开发工具为这次实例设置cookie,然后加载本地HTML文件40秒之后)
通过这个cookie,我们已经可以可靠的泄露一部分cookie的数据库,用UTF-16解码,解析被加密的值(‘V10’做前缀),然后使用web的加密API加密它们。在文章后面附上POC文件。
注意,我们现在仅仅使用一个payload设置单个cookie。这就意味着,如果UTF-16 payload解析失败,或者css解析被截断,那么测试就会失败。改善的方法是设置一些不同cookie值(--a, --b, --c),这样可以提高成功率。在后面我依然会附上成功的截图。

建议:

为了避免读取到敏感信息,在配置文件名前加一串随机的字符串(火狐中有类似的方式),这将增加那些攻击者难度。
并且,火狐的css字符串解析应该更加严格,如果发现一个NULL字节,就停止解析,这样可以减少泄露。
似乎最明智(最简单)的方式是在每一个Linux系统中使用独一无二的key。我猜想,本地的攻击者也会有寻找key的动机,但是攻击者只有部分读取权限,这还是能保护一些人。
这可能不是一个很严重问题,但是我觉得很有趣,希望你能喜欢。

[1] https://www.w3.org/TR/css-syntax-3/#%7B%7D-block-diagram
[2] https://cs.chromium.org/chromium/src/components/os_crypt/os_crypt_posix.cc?l=44
[3] 它可以从周围块中占有更多字节,因为我们我们不需要用16字节来寻找有效的块

附件在原文的最底部

源链接

Hacking more

...