通过滥用 CSS 解析来窃取本地文件内容

原文来自: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,完成攻击只需要两个条件

  • 敏感文件在固定(或者可预测)路径
  • 攻击者能注入内容到那些文件中
    Chrome的SQLite正好满足这两个条件,成为这次攻击者的理想对象。比如:
    //互联网上的随机页面
<script>
document.cookie = "foo{}*{--:bar=1337"; // 几分钟之后写入sqlite数据库  
</script>

本地文件(从默认路径~/Downloads/打开的文件)

<link rel="stylehseet" href="../Library/Application Support/Chrome/Default/Cookies">
<script>
var leak = getComputedStyle(document.body).getPropertyValue('--');
alert(leak);
</script>

上面的代码有时会很有效,但是由于文件巨大,很难控制payload在字符前面还是后面。他们中的有一些会破坏css的解析。为了提高成功的机会,我们使用一种叫"ile-massaging"的方法。
下面的poc不是很可靠,但是已经在Chrome stable 62 和 Canary 64 (Linux和osx机器上)测试成功,下面用例子来演示攻击者的操作

探针的概念

  • PoC 1 - 跨域重定向的泄露
    文件: redir.html
    描述:’~/Library/Application Support/Google/Chrome/Default/Current Session’这个文件里面包含当前请求的信息。有两个比较有趣的事情是,一部分信息被UTF-16编码(用了这种编码可以减少解析中断的提醒),并且框架中请求被很完美的收集到父类请求中。因此,我们能用框架来跨域并且能读到重定向的结果。我们仅仅需要确定css解析器是否通过提前关闭所有的块(blocks)[1]来处于适当的状态,我们只要简单添加“}])”字符就可以判断。

  • PoC 2 - 本地存储SQLite泄露(localstorage.html):
    文件: localstorage.html
    描述:在这个案例中,目标数据库存储文件存储在‘~/Library/Application Support/Google/Chrome/Default/Local Storage/leveldb/’。因为数据是被直接存储的并且我们能完全控制二进制数据,我们很容易把我们的payload编码成UTF-16,并且能被css解析器解析。而且,文件名会采用数字自增的方式命名,我们就可以爆破文件名,直到读取到我们注入的内容。
    这就会泄露其他网站和插件的敏感信息。

  • PoC 3 - cookie怪物
    文件: cookiemonster.html
    描述:正如上面提到,当页面设置cookie的之后,它会在几分钟之后写入到本地的SQLite数据库中。数据库的表结构为:

/*
creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY,
host_key TEXT NOT NULL,
name TEXT NOT NULL,
value TEXT NOT NULL,
path TEXT NOT NULL,
expires_utc INTEGER NOT NULL,
secure INTEGER NOT NULL,
httponly INTEGER NOT NULL,
last_access_utc INTEGER NOT NULL,
has_expires INTEGER NOT NULL DEFAULT 1,
persistent INTEGER NOT NULL DEFAULT 1,
priority INTEGER NOT NULL DEFAULT 1,
encrypted_value BLOB DEFAULT '',
firstpartyonly INTEGER NOT NULL DEFAULT 0
*/

攻击者能够控制cookie的‘name’和‘path’(这些值都是被加密的),可是,还是很容易创造包含payload的cookie,如果幸运的话,可以泄露出一些cookie。一件有趣的事情是,新的cookie会比老的cookie先写入(从文件偏移的角度来看),原因似乎是,SQLite开辟新的空间后,填充数据的方式是从底部到顶部(至少在某种程度上)。这些将帮助我们,因为我们对泄露已存在的cookie特别感兴趣(并且,css的解析是从顶到底的方式)

不幸的是,多数情况下,特殊字符会截断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都是已知的并且是固定值)
image
我们要找到一个有效的块B,它解码之后满足:

  • P0的字节是有效的字符(每个字节有2位的限制,且要小于32字节的熵)
  • P1的字节也是有效的字符。可是,因为payload的aes输出是固定的,我们可以限制B0的初始空间搜索,使P1 = B0 ^ AES(key,payload) 是一个有效的文本
    我们要找到一个有效的块B2,它解码之后满足:
  • P2 = payload ^ AES(key, B2) 的字节是有效的字符
  • P2的结尾是byte = 0x01 (最简单的有效的填充)

幸亏的是,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/#{}-block-diagram
[2] https://cs.chromium.org/chromium/src/components/os_crypt/os_crypt_posix.cc?l=44
[3] 它可以从周围块中占有更多字节,因为我们我们不需要用16字节来寻找有效的块

附件在原文的最底部

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 修改/etc/password文件添加用户的好处是可以快速添加用户,省去了使用用户管理工具的步骤。但是需要注意以下问题: 1.文件格式必须正确,否则可能导致用户无法登录或者系统崩溃。 2.必须以root权限进行操作。 3.密码必须进行加密存储,否则可能存在安全漏洞。 4.需要确保新用户属于正确的用户组,并且有合适的权限,否则可能会出现各种意外问题。 总之,修改/etc/password文件添加用户需要非常小心谨慎,以确保系统的安全和稳定。建议使用用户管理工具进行用户管理。 ### 回答2: 通过直接修改/etc/password文件来添加用户的好处是可以快速、方便地添加用户,特别是在批量添加多个用户的情况下,可以节省大量时间和工作量。同时,通过直接修改该文件,可以自定义用户的用户名、用户ID、主目录等信息。 然而,需要注意以下问题: 1. 安全性风险:直接编辑/etc/password文件需要root权限,因此存在潜在的安全风险。如果不小心删除或修改了重要的信息,可能导致系统无法正常启动或用户无法登录。 2. 错误风险:修改/etc/password文件时要非常小心,因为错误的更改可能导致用户账户出现问题,例如无法登录、权限问题等。因此,在编辑之前,务必备份该文件,并确保对其进行正确的修改。 3. 不可逆性:一旦修改了/etc/password文件,相关更改是不可逆转的。因此,在进行修改之前,应该仔细审查并确认所做的更改是正确和合理的。 4. 维护困难性:通过直接编辑/etc/password文件添加用户,会导致维护困难,特别是在需要频繁添加或删除用户的情况下。相比之下,使用专门的用户管理工具(如useradd命令)更为灵活和便捷,可以避免不必要的问题。 综上所述,通过直接修改/etc/password文件来添加用户虽然有快速方便的优势,但也存在安全和错误风险。因此,在操作前应做好备份,并谨慎修改。在需要频繁添加或删除用户的情况下,建议使用专门的用户管理工具来进行操作。 ### 回答3: 通过直接修改/etc/password文件来添加用户的好处是可以快速添加用户和设置密码,不需要借助图形界面或者命令行工具。同时,直接修改该文件还可以方便地对多个用户进行批量操作,提高了效率。 然而,需要注意的是这种方式存在一些问题。首先,直接修改/etc/password文件需要root权限,因此需要确保自己有足够的权限才能进行操作。其次,直接修改该文件可能会引发系统的不稳定和不安全,因为该文件中存储着所有用户的加密密码,一旦错误地修改了文件内容,可能导致用户无法登录或者安全漏洞的出现。 此外,直接修改/etc/password文件可能会造成某些系统工具的冲突或重复,例如用户管理工具可能无法正确地读取和管理被直接添加的用户。因此,在使用该方式添加用户时,需要确保与系统工具的正常协作,避免引发其他异常。 综上所述,通过直接修改/etc/password文件来添加用户的好处是快速、高效,但需要注意切勿滥用权限、修改错误或对系统其他功能产生干扰。同时,为了确保系统的稳定和安全,建议仅在熟悉该文件结构和操作规范的情况下进行修改,或是使用系统提供的用户管理工具来添加和管理用户。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值