`open-url` command allows opening unlimited number of tabs pointing to arbitrary URLs

Disclosed: 2019-04-23 12:05:54 By metnew To grammarly
Medium
Vulnerability Details
## Summary Attacker could trigger Grammarly extension's `open-url` command to open any number of tabs pointing to any origin (including internal, e.g. `chrome://`) and cause "infinite Chrome DoS" if attacker's page is pinned. ## Description ### Page could Init Grammarly popup editor [no user gesture, helper] Events have `isTrusted` property, which allows to determinate, whether current event is trusted(initiated by user). Grammarly popup editor could be initiated by page. As I understood: injected content script could successfully emit events to background page only if popup was initiated earlier. That means, attacker needs to initiate the popup somehow to communicate with background page through injected content script. > Not sure about the root cause of this behavior. Probably, because popup is created by background page origin, that's why background page becomes accessible after this. ### send `open-url` to content script Active page could send commands to Grammarly content script using `window.postMessage`. Command structure: ``` js window.postMessage({ grammarly: true, action: 'open-url', url: 'file:///etc/passwd' }, "*") ``` ### `open-url` handling in content script Grammarly content script "parses" commands using this snippet: ``` js function Z(e) { var t, n = e.action; "edit" === n && U(e), "close" === n && te(), "initialized" === n && (t = "Premium" === e.userType ? "freemium-plus" : "freemium", O.documentElement.setAttribute("data-type", t), setTimeout(function () { return T.el.style.background = "transparent" }, 300)), "socket" === n && p.emitBackground(b.MessageTypes.client, e), "setSettings" === n && N(e.data), "tracking" === n && e.method && g.call(e.method, e.param, e.props), "popup-editor-fix" === n && P(), "open-url" === n && (!0 === e.upgradeHookUrl && (y.gnar.getPremiumButtonClick(e.placement || "popupEditor"), g.felog.userUpgradeClick(e.placement || "popupEditor")), p.emitBackground("open-url", e.url)) } ``` > There are multiple problems in this code, however, this report only about `open-url`. As you see, `open-url` commands are sent to background page. ### `open-url` handling on background page `open-url` command is handled by this snippet: ```js e.prototype.open = function (e, t) { return o.SafePromise.create(function (n, o) { chrome.tabs.create({ url: e, active: t }, function (e) { r.handleChromeError(function () { return n(e) }, o) }) }) } ``` > *More details in "Impact"* #### Step by Step 1. Page sends a `open-url` command to content script [without user gesture, with attacker's `<url>` property] 2. Content script sends `open-url` command to background page 3. Background page opens new tab using `chrome.tabs` on `<url>` ## Browsers Verified In: Chrome 70.0.3508.0 Canary Chrome 68.0.3440.75 Stable ## Steps To Reproduce: ### `file://` 1. open `file-url.html` (no gesture required) 2. Extension opens **two** tabs on `file:///etc/passwd` ### `chrome://version` 1. open `chrome-url.html` (no gesture required) 2. Extension opens **two** tabs on `chrome://version` > PoCs are reliable, however, if it doesn't works for you, try to adjust timers in script. ## Supporting Material/References: screencast for `chrome://version` and `file:///etc/passwd` attached. > Screencast for infinite DoS not attached, but I've attached PoC for this case, so that you can try 😈 > Note: Works against logged in users. Probably, could be modified to work against unlogged in users. ## Impact ### Infinite number of new tabs As you see, background page uses `chrome.tabs` under the hood. As opposite to `window.open`, `chrome.tabs` doesn't have limit on number of new tabs to open (only 1 tab is allowed for `window.open` without user's gestures). That means page could open **as many tabs as it wants** using `open-url` command. **IMPACT**: this behavior could be abused by **malicious advertisement websites**. #### Open pages on restricted origins Grammarly extension has access to `<all_urls>`. That means it's possible to open URLs from restricted origins (`file://`, `chrome://`, `chrome-devtools://`, `chrome-extension://`, etc). **IMPACT:** This behavior is extremely helpful when exploiting Chrome vulns or other 3rd-party web extensions (e.g. trigger vuln in `chrome-devtools://` [like this](https://bugs.chromium.org/p/chromium/issues/detail?id=607939)) > **NOTE:** I didn't test this on Win machine. AFAIK, it was possible to trigger executables by navigating to local `.lnk/.url` files. #### "Infinite Chrome DoS" [requires attacker's page being pinned] Navigation to `chrome://quit` closes browser. However, if tab is pinned, Chrome reopens this tab on start. As of this vulnerability doesn't require user interaction, that could potentially lead to Chrome DoS. > (browser opens -> pinned page loads -> browser closes -> browser opens -> pinned page loads -> ...) **IMPACT:** I guess that most users wouldn't find a smarter solution than uninstalling extensions πŸ˜‰or reinstalling the browser.
Actions
View on HackerOne
Report Stats
  • Report ID: 389076
  • State: Closed
  • Substate: resolved
  • Upvotes: 36
Share this report