Project: chromium Issues People Development process History Sign in
New issue
Advanced search Search tips
Starred by 3 users
Status: Fixed
Owner:
Closed: Dec 2016
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 1
Type: Bug-Security



Sign in to add a comment
Security: non-interactive request forcing
Reported by m...@michaelruddy.com, Dec 7 2016 Back to list
VULNERABILITY DETAILS

When a user starts the browser, it immediately sends a UDP multicast SSDP request to 239.255.255.250:1900. The purpose of this request is to gather info from other local network devices that Chrome could later use for screen casting.

The problem is that the effect of this functionality is that the browser asks the network to suggest a set of URLs that it should run HTTP GET requests on at startup. Then it runs the requests, all without any user interaction or awareness.

The HTTP connections persist cookies that come back in the responses. This could be used to force cookies on the user (and/or overwrite existing cookies).
If a URL has the HTTP scheme, the browser will send, in the clear, persisted cookies not marked "secure" (for domains that are NOT in the HSTS preload list).
This could be used to perform CSRF, as the victim user, against vulnerable sites (an attacker can specify a list of URLs that he would like the browser to visit).

Basically, this appears to be a LAN centered feature that does not properly limit what it will request, and it sends and sets too much data (e.g. cookies).
A non-MITM attacker could use this to perform CSRF against a vulnerable site, without user interaction.
A MITM attacker could use this to inspect cookies not marked secure, set/force/overwrite cookies, and all the other typical stuff available to a MITM attacker, but without requiring user initiated action, other than opening the browser.

When using incognito mode, the cookies used and set by this function are the cookies of non-incognito mode.
I did not expect that non-incognito mode persistent cookies could be changed while running in incognito mode. That seems like a violation.

Even if a user has never navigated to a site, persistent cookies can be set for when they do actually navigate there.
Even if a user uses incognito mode and types in https (or uses https bookmarks), a non-HSTS site is vulnerable to cookie forcing/injection with this enabled.

Disabling chrome://flags/#media-router stops this functionality from running at startup. Perhaps make this disabled by default until it's worked out (it is enabled by default right now).
However, this same thing runs when "Cast..." is selected from the menu.

Here's the related code:
https://cs.chromium.org/chromium/src/chrome/browser/extensions/api/dial/dial_service.cc

VERSION
Chrome Version: 55.0.2883.75 (64-bit) stable
Operating System: Ubuntu 16.04.1 LTS

REPRODUCTION CASE

The attached BadSSDP.java POC java program listens for such a multicast request and returns responses with URLs that it would like the browser to request.
The attached poc.js is a small node.js HTTP server that sets cookies depending on the request received (a similarly configured local web server could be used instead for testing).

1) clear all cookies and close all google chrome processes
2) set example.com to resolve to 127.0.0.1 in /etc/hosts (this just makes testing easier. a real attacker could arpspoof to get MITM to be able to inspect, inject, modify etc...)
3) /opt/node-v7.2.1-linux-x64/bin/node ./poc.js &
4a) javac BadSSDP.java;
4b) java BadSSDP &
5) open chrome incognito window (packets #1-38 in attached packet capture)
6) wait a few seconds then close chrome incognito window (you actually don't have to wait long at all, but just to make sure you see what's going on...)
7) open chrome incognito window and notice that cookies are sent that were set automatically by step #5 (packets #39-76 in attached packet capture)
8) open new non-incognito window and navigate to http://example.com:8080/ and notice that cookies are sent that were set automatically by step #5 (not included in the packet capture, just look at dev console etc...)

Note: While running this test, something that might trip you up are host-based firewall rules. If so, allow UDP port 1900 packets in and out. This functionality relies on that traffic being allowed for it to ever work, so the assumption must be that users allow that traffic already.
 
packets.pcap
13.1 KB Download
BadSSDP.java
1.8 KB View Download
poc.js
641 bytes View Download
Cc: mfo...@chromium.org imch...@chromium.org
Labels: M-55 Security_Severity-Medium Pri-1
Cc: -mfo...@chromium.org
Labels: OS-All
Owner: mfo...@chromium.org
Status: Assigned
As an initial mitigation we should filter device description URL hosts to be RFC 1918 addresses.

Longer term, need to think about how to keep these requests independent from cookie store.

> how to keep these requests independent from cookie store.

Do we need to support cookies at all in this codepath? If not, can we do what IntranetRedirectDetector does?

    // We don't want these fetches to affect existing state in the profile.
    fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE |
                          net::LOAD_DO_NOT_SAVE_COOKIES |
                          net::LOAD_DO_NOT_SEND_COOKIES |
                          net::LOAD_DO_NOT_SEND_AUTH_DATA);
Project Member Comment 5 by sheriffbot@chromium.org, Dec 10 2016
Labels: Security_Impact-Stable
Comment 6 by mfo...@chromium.org, Dec 13 2016
No we don't need cookies.  To take advantage of the code path you suggest, we would need to plumb an extension API to call the IntranetRedirector, unless one already exists.

My proposal isn't that we should use the IntranetRedirector codepath directly. Instead, the question is whether we can, after the Dial API discovery phase obtains URLs, we fetch those discovered URLs using the Load Flags that suppress unwanted headers and caching behavior. 
Comment 8 by mfo...@chromium.org, Dec 13 2016
Yes, that makes complete sense.
Components: Internals>Cast
Status: Fixed
The issue pointed out by the original poster should be fixed in Chrome Canary running Media Router 5716.1220.0 or newer.  I am working on a more comprehensive fix, but it won't land for another few days.


Project Member Comment 11 by sheriffbot@chromium.org, Dec 22 2016
Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify
Labels: reward-topanel
Project Member Comment 13 by sheriffbot@chromium.org, Jan 3 2017
Labels: Merge-Request-56
Comment 14 by dimu@chromium.org, Jan 4 2017
Labels: -Merge-Request-56 Merge-Approved-56 Hotlist-Merge-Approved
Your change meets the bar and is auto-approved for M56 (branch: 2924)
Project Member Comment 15 by sheriffbot@chromium.org, Jan 9 2017
This issue has been approved for a merge. Please merge the fix to any appropriate branches as soon as possible!

If all merges have been completed, please remove any remaining Merge-Approved labels from this issue.

Thanks for your time! To disable nags, add the Disable-Nags label.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Labels: -Hotlist-Merge-Approved
Project Member Comment 17 by bugdroid1@chromium.org, Jan 10 2017
The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/90824416d3eeae5ec6013b250123df65e9d48032

commit 90824416d3eeae5ec6013b250123df65e9d48032
Author: mfoltz <mfoltz@chromium.org>
Date: Tue Jan 10 22:34:11 2017

Adds chrome.dial.fetchDeviceDecription API.

This API fetches the device description for a DIAL device, given a label for a device already discovered.

The request is configured to not send/receive cookies, ignore proxies, and ignore redirects.

Requests are retried with backoff on 5XX responses.

The response is validated in multiple ways:
- Valid Application-URL: header value
- Response body is a valid UTF-8 string
- Response body is <= 256kb

Additional validations are possible by following the DIAL spec closely at the risk of ignoring some devices.  See comments in device_description_fetcher.cc for details.

Note: The API function implementation is complicated by thread hopping.  See comments in dial_api.h for how this may be improved in the future.

BUG= 671932 
TESTED=Manually, unit tests, API test

Review-Url: https://codereview.chromium.org/2583853004
Cr-Commit-Position: refs/heads/master@{#442713}

[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/BUILD.gn
[add] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/api/dial/device_description_fetcher.cc
[add] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/api/dial/device_description_fetcher.h
[add] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/api/dial/device_description_fetcher_unittest.cc
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/api/dial/dial_api.cc
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/api/dial/dial_api.h
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/api/dial/dial_apitest.cc
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/api/dial/dial_device_data.cc
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/api/dial/dial_device_data.h
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/api/dial/dial_registry.cc
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/browser/extensions/api/dial/dial_registry.h
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/common/extensions/api/dial.idl
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/test/BUILD.gn
[add] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/test/data/extensions/api_test/dial/experimental/fetch_device_description.html
[add] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/chrome/test/data/extensions/api_test/dial/experimental/fetch_device_description.js
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/extensions/browser/extension_function_histogram_value.h
[modify] https://crrev.com/90824416d3eeae5ec6013b250123df65e9d48032/tools/metrics/histograms/histograms.xml

Project Member Comment 18 by sheriffbot@chromium.org, Jan 12 2017
This issue has been approved for a merge. Please merge the fix to any appropriate branches as soon as possible!

If all merges have been completed, please remove any remaining Merge-Approved labels from this issue.

Thanks for your time! To disable nags, add the Disable-Nags label.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Labels: -reward-topanel reward-unpaid reward-1000
Congratulations! The panel decided to award $1,000 for this bug!
Thanks! I signed up as a vendor a while back, do I need to do anything else?
mike@ - in that case no, this will be included in the next payment run, so the money should be with you in a few weeks!
Labels: -reward-unpaid reward-inprocess
Labels: -M-55 M-56
This reward payment has been inprocess for over a month, is there something wrong? All my info is still the same. Thanks!
Labels: M-57 Release-0-M57
Labels: CVE-2017-5042
Project Member Comment 28 by sheriffbot@chromium.org, Mar 30
Labels: -Restrict-View-SecurityNotify allpublic
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Labels: -Merge-Approved-56
Sign in to add a comment