PRELOADER

当前文章 : 《溢出三部曲》

12/2/2019 —— 

溢出三部曲

溢出不仅仅是Websec中的日常术语。今天我要分享三个有趣的案例,都是关于Twitter的漏洞。

HTTP响应与head溢出分离

此问题清楚地说明了HTTP Response Splitting与CRLF注入的不同之处。通常99个HTTP响应拆分漏洞是由CRLF注入引起的,而这个漏洞则滥用了一个不涉及注入CRLF的不同缺陷。

他们的补丁——在同一页面上的输入仍然缺乏适当的验证,这导致了这个问题的发现。在其中一个输入参数中创建足够长的值时,会直接显示HTML源代码。

这个不寻常的场景是由于缺少Content-Type。实际上,应该沿响应发送的一半头字段被分成两半。服务器似乎只处理响应头的第一个8kB,

然后它感觉到响应可能不完整或被破坏,因此返回了HTTP 500(内部服务器错误)。有趣的是在重新发出相同的请求时返回截断的部分

(让我们称之为第二个响应),由于我们可以控制在响应头中反映的值,我们可以注入一个字符串,使其长度加上前面的头字段’略超过8kB,

然后我们注入的字符串的最后一个字符突然变成下一个字符串的开头响应标题。

在这种情况下,在report_user_id后注入像AAA[…]AAA:foobar,AAA:foobar分别变成:名称报头字段AAA和值foob​​ar的第二响应。

显然,我们可以用标准化的标题字段(例如Access-Control-Request-Origin)替换它来做真正的危害。

但是,要确定应该添加多少填充以填充仅8k并不容易,因为有时响应头可能会有所不同。我们需要一种确定性的方法将它截断到我们想要的

任何地方。快速模糊显示服务器在标题字段名称中占用空格(U + 0020)。换句话说,我们可以使用空格作为填充。总结一下:

1. 前置一堆空的空格(略小于8kB,否则服务器拒绝HTTP 414的请求(Request-URI太长))到一个头字段进行攻击
1. 将精心设计的值放入其中一个输入参数中
1. 让访问者两次访问该页面,因为只有第二次才会触发payload

最后一个挑战是浏览器用%20编码空白空间。问题是它花费3个字节而不是1个,这使我们的预期payload(记住请求URI需要小于8kB,如上所述)幸运的是,加号(+)也被接受为编码的空白空间。

其实,我并不知道这个具体的原因。这可能是一个缓冲实现错误,但我无法确定。无论如何,这种奇怪的行为是固定的,但仍然没有任何输入验证。

最终攻击payload

https://twitter.com/i/safety/report_story?next_view=report_story_start&source=reporttweet&reported_user_id=1&reporter_user_id=1&is_media=true&is_promoted=true&reported_tweet_id=+++[...]+++set-cookie:foobar

完整的响应头:

HTTP/1.1 200 OK
set-cookie: foobar
x-response-time: 229
x-connection-hash: 4f7c08fce85fe4801b3b24f05764fc84
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-transaction: f9709a489ba395b5
x-twitter-response-tags: BouncerCompliant
x-xss-protection: 1; mode=block

使用Cookie炸弹拒绝服务

上述发现实际上是这一发现的一小部分。由于输入反映在Set-Cookie中,我们可以控制这些特定cookie的值及其属性(例如Domain,Expires)。

以前这意味着CSRF保护旁路(使用逗号(,)作为cookie分隔符fwiw),但现在不再是这种情况,因为Twitter现在将cookie与会话中的cookie进行比较。但是,攻击者可以使用Cookie Bomb来利用它。

Cookie Bomb是Egor Homakov介绍的术语。攻击本身并不是什么新鲜事,但很少有人真正研究它。它的主要思想是服务器拒绝具有异常大的head

请求。确切的数字可能在不同的服务器上有所不同,但通常请求标头不能大于8kB。通过滥用此功能,攻击者可以强迫被攻击者接受一堆

大型cookie。它的作用是,受害者对相应网站的所有请求都将包含一个非常大的cookie,导致服务器拒绝受害者的任何请求(即拒绝服务)。

通过操纵不同的cookie属性可以进一步改进攻击:

域名:而不仅仅是example.com,.example.com将cookie应用于所有子域名,使整个服务瘫痪。
cookie过期:默认情况下,除非另有说明,否则在浏览器重新启动后将销毁cookie,相反,攻击者可以利用它来永久锁定受害者,直到他们手动删除cookie。
路径:将其设置为根路径(/)可以最大化的影响页面数。

行动中的攻击

攻击payload(无需编码以实现可读性):

1. https://twitter.com/i/safety/report_story?next_view=report_story_start&reported_user_id=000[...]000;Expires=Wed, 02 Apr 2025 12:21:55 GMT;Path=/;Domain=.twitter.com&reporter_user_id=1&is_media=true&is_promoted=true&reported_tweet_id=000[...]000;Expires=Wed, 02 Apr 2025 12:21:55 GMT;Path=/;Domain=.twitter.com

响应头:

1. HTTP/1.1 200 OK
1. [...]
1. set-cookie: reported_user_id=000[...]000;Expires=Wed, 02 Apr 2025 12:21:55 GMT;Path=/;Domain=.twitter.com
1. set-cookie: reported_tweet_id=000[...]000;Expires=Wed, 02 Apr 2025 12:21:55 GMT;Path=/;Domain=.twitter.com
1. [...]

您可能想知道为什么要使用两个cookie而不是一个。那是因为一个cookie只能包含最多4kB的数据。

当被攻击者访问该页面后,我们的攻击已经开始进行。

解决方法

解决的方法:始终验证用户输入,包括长度。幸运的是,这次Twitter通过适当的输入验证来修复它。此外,知道不要让用户设置任意cookie值也很重要。

基于DOM的Cookie炸弹

DOM上的Cookie API很乱。只有一个属性可以与之交互(即document.cookie)。开发人员需要特别注意确保正确使用它。在这里,我想在Twitter上展示另一个Cookie炸弹问题。

分析

Twitter曾经使用cookie跟踪主题标签和引用者。他们是这样做的:

function d(a) {
[...]
var b = document.referrer || "none",
d = "ev_redir_" + encodeURIComponent(a) + "=" + b + "; path=/";
document.cookie = d;
[...]
}
[...]
window.location.hash != "" && d(window.location.hash.substr(1).toLowerCase())

简而言之,如果访问者来自其他网站,它会将document.hash和document.referrer中的主题标签记录到cookie中。

然而cookie值(引用者)未被编码或验证,允许攻击者设置任意cookie值。有一点需要知道的是,浏览器会对document.referrer中的某些字符

进行编码。为了最大化影响,我们需要能够注入一些关键字符,即分号(;)和等号(=),以操纵cookie属性。所有的浏览器似乎都没有触及它们

但是空的空间被编码。没有它我们不能将有效的GMT日期(Wdy,DD-Mon-YYYY HH:MM:SS GMT)分配给Expires。

我们可以替换它Max-age告诉浏览器cookie应该在多少秒后失效,但某些浏览器(例如Internet Explorer)无法识别此类属性。

下表显示了在每个浏览器中可以使用哪些charactors替换Expires中的空白区域:

Chrome
33 (!), 34 ("), 35 (#), 36 ($), 37 (%), 38 (&), 39 ('), 40 ((), 41 ()), 42 (*), 43 (+), 44 (,), 45 (-), 46 (.), 47 (/), 60 (<), 61 (=), 62 (>), 63 (?), 64 (@), 91 ([), 92 (\), 93 (]), 94 (^), 95 (_), 96 (`), 123 ({), 124 (|), 125 (}), 126 (~)
Firefox
9 (TAB), 40 ((), 41 ()), 44 (,), 45 (-), 47 (/), 91 ([), 93 (])
Internet Explorer
Anything except alphanumeric and semi-colon
Safari
9 (TAB)

所以大多数浏览器都接受古怪的日期。你可以用类似的东西来测试它document.cookie = 'foo=bar; expires=Thu,01[Jan/2025^00:00:01+GMT'

攻击手段

1. 准备一个网址为`https://attacker.com/?AAA[...]AAA;domain=.twitter.com:expires=Thu,01 [Jan / 2025 ^ 00:00:01 + GMT`
1. 将受害者重定向到`https://twitter.com/#foo和https://twitter.com/#bar`以设置两个大型Cookie(由于每个Cookie限制为4kB)

结论

验证用户输入是很重要的事情,即使是冗长的输入也可能会导致您的应用出现问题

原文链接:https://blog.innerht.ml/page/10/