New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Security: Stack Buffer Overflow in QuicClientPromisedInfo::OnPromiseHeaders

Reported by nedwilli...@gmail.com, Oct 24 2017

Issue description

VULNERABILITY DETAILS
The QUIC Protocol has a feature called "Server Push", where a server
can push resources to a client before they are explicitly requested,
to prevent unneeded round-trips. When handling push headers,
QuicClientPromisedInfo::OnPromiseHeaders assumes that the `:method`
header is present when receiving a server push, but it may not be.

from net/quic/core/quic_client_promised_info.cc:
```
void QuicClientPromisedInfo::OnPromiseHeaders(const SpdyHeaderBlock& headers) {
  // RFC7540, Section 8.2, requests MUST be safe [RFC7231], Section
  // 4.2.1.  GET and HEAD are the methods that are safe and required.
  SpdyHeaderBlock::const_iterator it = headers.find(kHttp2MethodHeader);
  DCHECK(it != headers.end());
  if (!(it->second == "GET" || it->second == "HEAD")) {
    QUIC_DVLOG(1) << "Promise for stream " << id_ << " has invalid method "
                  << it->second;
    Reset(QUIC_INVALID_PROMISE_METHOD);
    return;
  }
```

Here, if the `kHttp2MethodHeader` was not found, it will point to
the end of the headers map, which is allocated on the stack in
net/quic/chromium/quic_chromium_client_stream.cc in function
QuicChromiumClientStream::OnPromiseHeaderList.

The function goes on to dereference the OOB `it->second`.

SpdyHeaderBlock::const_iterator has a custom `operator->()`
which calls `SpdyHeaderBlock::HeaderValue::as_pair()`, performing
an OOB write. On Linux's libcxx, the underlying std::list::end is
on the stack, and on Windows, it is in the heap. I've observed
the following PoC repro attempting to dereference ASCII from the
heap as the linked list next/prev pointers, so exploitation seems
easier on Windows in the current stable build; on the current Linux
stable I believe it always crashes memcpy'ing off the end of the heap.

I've attached a patch that fixes the vulnerability.

VERSION
Chrome Version: Chrome 62 Stable
Operating System: All

REPRODUCTION CASE
Apply the attached server.patch so the sample QUIC server will send empty PUSH_PROMISE headers.

Setup and run quic_server using the guide at https://www.chromium.org/quic/playing-with-quic,
substituting my attached sources files from `www.example.org.tar`:
`out/Default/quic_server --quic_response_cache_dir=/path/to/attached/www.example.org
--certificate_file=net/tools/quic/certs/out/leaf_cert.pem
--key_file=net/tools/quic/certs/out/leaf_cert.pkcs8 --v=3`

Launch Chrome 62 with `--no-proxy-server --origin-to-force-quic-on=www.example.org:443 --host-resolver-rules='MAP www.example.org:443 127.0.0.1:6121' https://www.example.org`.
I used `asan-linux-stable-62.0.3202.62` to generate the asan.log output.

FOR CRASHES, PLEASE INCLUDE THE FOLLOWING ADDITIONAL INFORMATION
Type of crash: Browser
Crash State: See attached asan.log
 
asan.log
10.3 KB View Download
server.patch
1.3 KB Download
www.example.org.tar
8.5 KB Download
My previous fix still had an OOB access in debug mode when logging the error. I went ahead and added an explicit case instead. These iterator bugs are pernicious!
fix.patch
1.9 KB Download
Components: Internals>Network>QUIC
Labels: OS-Android OS-Chrome OS-Linux OS-Mac OS-Windows
Thanks for the report!
Owner: rch@chromium.org
Status: Assigned (was: Unconfirmed)
Haven't had a chance to verify this quite yet, but will update with severity and impact soon.

rch: Would you mind taking a look at this?

Comment 4 by palmer@chromium.org, Oct 31 2017

Cc: nhar...@chromium.org
Labels: OS-Fuchsia
As far as I can tell, this is an OOB read, not write, and it doesn't seem to enable any kind of exfiltration of the OOB content:

void QuicClientPromisedInfo::OnPromiseHeaders(const SpdyHeaderBlock& headers) {
  // RFC7540, Section 8.2, requests MUST be safe [RFC7231], Section
  // 4.2.1.  GET and HEAD are the methods that are safe and required.
  SpdyHeaderBlock::const_iterator it = headers.find(kHttp2MethodHeader);
  DCHECK(it != headers.end());
  if (!(it->second == "GET" || it->second == "HEAD")) {
    QUIC_DVLOG(1) << "Promise for stream " << id_ << " has invalid method "
                  << it->second;
    Reset(QUIC_INVALID_PROMISE_METHOD);
    return;
  }
  if (!SpdyUtils::UrlIsValid(headers)) {
    QUIC_DVLOG(1) << "Promise for stream " << id_ << " has invalid URL "
                  << url_;
    Reset(QUIC_INVALID_PROMISE_URL);
    return;
  }
  if (!session_->IsAuthorized(SpdyUtils::GetHostNameFromHeaderBlock(headers))) {
    Reset(QUIC_UNAUTHORIZED_PROMISE_URL);
    return;
  }
  request_headers_.reset(new SpdyHeaderBlock(headers.Clone()));
}

So, I'd call this a browser process DoS. We don't consider such bugs to be security vulnerabilities (https://chromium.googlesource.com/chromium/src/+/master/docs/security/faq.md#Are-denial-of-service-issues-considered-security-bugs).

However, it might be that there's something I'm missing — I'm not an expert in this area. I'll defer to rch and nharper on that. But, if you agree, please feel free to change the Type to Bug, and remove the view restriction.
I agree that when I first found this, it appeared to be a useless OOB read. But weeks later when I went to report it, I was stunned to find that `headers.find` returns a completely custom iterator that allows OOB write. Note that in the asan.log a few lines up from the first read (when ASAN aborts immediately) the read value goes on to be assigned here:

```
const std::pair<SpdyStringPiece, SpdyStringPiece>&
SpdyHeaderBlock::HeaderValue::as_pair() const {
  pair_.second = ConsolidatedValue();
  return pair_;
}
```

What makes this particularly bad IMO is that ConsolidatedValue has side effects (joining the string within the object), all of this taking place out of bounds on the stack. As I mentioned, I did repro this on a fresh Chrome 62 install with a read/write on corrupted registers.

I'll give a shot at heap spraying on Windows to better demonstrate the severity, hopefully by the end of the week.

Comment 6 by palmer@chromium.org, Oct 31 2017

Labels: Security_Impact-Stable Pri-0
#5: Yeah, see, I was afraid something like that might happen. :) OOB write would make this a Critical, I believe. To prove that, you don't necessarily need to build a working proof of concept, just show that the vulnerable snippet you pasted above is reachable.
I have some repro instructions in the initial report. To prove it reaches that as_pair code snippet, I actually just kept applying `__attribute__((no_sanitize_address))` at each crashing function to see how far it would go. It led to a write then a memcpy (!). Whoever owns the fix here should be able to verify that. Cheers!
Labels: M-62
Marking M-62
Cc: awhalley@chromium.org cbentzel@chromium.org
Cc: palmer@chromium.org
Cc: lassey@chromium.org

Comment 12 by rch@chromium.org, Nov 1 2017

I'll get a fix landed ASAP.
Labels: M-61

Comment 14 by rch@chromium.org, Nov 1 2017

Cc: ckrasic@chromium.org

Comment 15 by rch@chromium.org, Nov 1 2017

Cc: zhongyi@chromium.org
Labels: Security_Severity-Critical
Labels: ReleaseBlock-Stable M-63
Project Member

Comment 19 by bugdroid1@chromium.org, Nov 1 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/7a6484fa7b7f86ea06749bfc9d10bb67b145140b

commit 7a6484fa7b7f86ea06749bfc9d10bb67b145140b
Author: Ryan Hamilton <rch@chromium.org>
Date: Wed Nov 01 11:35:00 2017

Fix Stack Buffer Overflow in QuicClientPromisedInfo::OnPromiseHeaders

BUG= 777728 

Cq-Include-Trybots: master.tryserver.chromium.android:android_cronet_tester;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I6a80db88aafdf20c7abd3847404b818565681310
Reviewed-on: https://chromium-review.googlesource.com/748425
Reviewed-by: Zhongyi Shi <zhongyi@chromium.org>
Commit-Queue: Ryan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#513105}
[modify] https://crrev.com/7a6484fa7b7f86ea06749bfc9d10bb67b145140b/net/quic/core/quic_client_promised_info.cc
[modify] https://crrev.com/7a6484fa7b7f86ea06749bfc9d10bb67b145140b/net/quic/core/quic_client_promised_info_test.cc

Project Member

Comment 20 by sheriffbot@chromium.org, Nov 1 2017

Labels: -M-61
Project Member

Comment 21 by bugdroid1@chromium.org, Nov 1 2017

Labels: merge-merged-3255
The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/f31b7c4c2e2aab26ffef3a0a3dc852439a3ac9dd

commit f31b7c4c2e2aab26ffef3a0a3dc852439a3ac9dd
Author: Ryan Hamilton <rch@chromium.org>
Date: Wed Nov 01 18:09:11 2017

Fix Stack Buffer Overflow in QuicClientPromisedInfo::OnPromiseHeaders

BUG= 777728 

Cq-Include-Trybots: master.tryserver.chromium.android:android_cronet_tester;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I6a80db88aafdf20c7abd3847404b818565681310
Reviewed-on: https://chromium-review.googlesource.com/748425
Reviewed-by: Zhongyi Shi <zhongyi@chromium.org>
Commit-Queue: Ryan Hamilton <rch@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#513105}(cherry picked from commit 7a6484fa7b7f86ea06749bfc9d10bb67b145140b)
Reviewed-on: https://chromium-review.googlesource.com/748828
Reviewed-by: Claude Masso <cmasso@chromium.org>
Cr-Commit-Position: refs/branch-heads/3255@{#2}
Cr-Branched-From: fc2679dfa73c1dc102d86832ef049359f433c314-refs/heads/master@{#513029}
[modify] https://crrev.com/f31b7c4c2e2aab26ffef3a0a3dc852439a3ac9dd/net/quic/core/quic_client_promised_info.cc
[modify] https://crrev.com/f31b7c4c2e2aab26ffef3a0a3dc852439a3ac9dd/net/quic/core/quic_client_promised_info_test.cc

Comment 22 by rch@chromium.org, Nov 1 2017

This also needs to merged to M63, right? Shall I do that now?

Comment 23 by rch@chromium.org, Nov 1 2017

Labels: Merge-Request-63 Merge-Request-62
Project Member

Comment 24 by sheriffbot@chromium.org, Nov 1 2017

Labels: -Merge-Request-63 Merge-Review-63 Hotlist-Merge-Review
This bug requires manual review: M63 has already been promoted to the beta branch, so this requires manual review
Please contact the milestone owner if you have questions.
Owners: cmasso@(Android), cmasso@(iOS), gkihumba@(ChromeOS), govind@(Desktop)

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Labels: -Merge-Request-62 -Merge-Review-63 Merge-Approved-62 Merge-Approved-63
Approving merge to both M62 and M63. 
M62 branch: 3202
M63 branch: 3239

Priority should be to merge to M62 first, and then M63. 


Project Member

Comment 26 by bugdroid1@chromium.org, Nov 1 2017

Labels: -merge-approved-62 merge-merged-3202
The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/159a410566da34aa646806111397b1afe73d538b

commit 159a410566da34aa646806111397b1afe73d538b
Author: Ryan Hamilton <rch@chromium.org>
Date: Wed Nov 01 22:36:01 2017

[m62 merge] Fix Stack Buffer Overflow in QuicClientPromisedInfo::OnPromiseHeaders

BUG= 777728 
TBR=rch@chromium.org

(cherry picked from commit 7a6484fa7b7f86ea06749bfc9d10bb67b145140b)

Cq-Include-Trybots: master.tryserver.chromium.android:android_cronet_tester;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I6a80db88aafdf20c7abd3847404b818565681310
Reviewed-on: https://chromium-review.googlesource.com/748425
Reviewed-by: Zhongyi Shi <zhongyi@chromium.org>
Commit-Queue: Ryan Hamilton <rch@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#513105}
Reviewed-on: https://chromium-review.googlesource.com/750063
Reviewed-by: Ryan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/branch-heads/3202@{#767}
Cr-Branched-From: fa6a5d87adff761bc16afc5498c3f5944c1daa68-refs/heads/master@{#499098}
[modify] https://crrev.com/159a410566da34aa646806111397b1afe73d538b/net/quic/core/quic_client_promised_info.cc
[modify] https://crrev.com/159a410566da34aa646806111397b1afe73d538b/net/quic/core/quic_client_promised_info_test.cc

Project Member

Comment 27 by bugdroid1@chromium.org, Nov 1 2017

Labels: -merge-approved-63 merge-merged-3239
The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/d36a49798c97641cd6c48c3e8f730ad44cc67bb0

commit d36a49798c97641cd6c48c3e8f730ad44cc67bb0
Author: Ryan Hamilton <rch@chromium.org>
Date: Wed Nov 01 22:42:37 2017

Fix Stack Buffer Overflow in QuicClientPromisedInfo::OnPromiseHeaders

BUG= 777728 
TBR=rch@chromium.org

(cherry picked from commit 7a6484fa7b7f86ea06749bfc9d10bb67b145140b)

Cq-Include-Trybots: master.tryserver.chromium.android:android_cronet_tester;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I6a80db88aafdf20c7abd3847404b818565681310
Reviewed-on: https://chromium-review.googlesource.com/748425
Reviewed-by: Zhongyi Shi <zhongyi@chromium.org>
Commit-Queue: Ryan Hamilton <rch@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#513105}
Reviewed-on: https://chromium-review.googlesource.com/750065
Reviewed-by: Ryan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/branch-heads/3239@{#337}
Cr-Branched-From: adb61db19020ed8ecee5e91b1a0ea4c924ae2988-refs/heads/master@{#508578}
[modify] https://crrev.com/d36a49798c97641cd6c48c3e8f730ad44cc67bb0/net/quic/core/quic_client_promised_info.cc
[modify] https://crrev.com/d36a49798c97641cd6c48c3e8f730ad44cc67bb0/net/quic/core/quic_client_promised_info_test.cc

Labels: M-61 Merge-Approved-61
rch@ - for Enterprise, we provide N-1 version support (specifically for Enterprises that have this signed in their contract). We've agreed to merge critical security patches into N-1 version. Can you please merge this to M61 as well for that purpose? This won't be released unless a customer specifically requests an M61 copy. 

Branch:3163

Comment 29 by rch@chromium.org, Nov 1 2017

Labels: Merge-Request-61
Will do!
Project Member

Comment 30 by bugdroid1@chromium.org, Nov 2 2017

Labels: -merge-approved-61 merge-merged-3163
The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/34ae85f6bc596af851096f028aded7c09a44ead5

commit 34ae85f6bc596af851096f028aded7c09a44ead5
Author: Ryan Hamilton <rch@chromium.org>
Date: Thu Nov 02 00:12:43 2017

[m61 merge] Fix Stack Buffer Overflow in QuicClientPromisedInfo::OnPromiseHeaders

BUG= 777728 
TBR=rch@chromium.org

(cherry picked from commit 7a6484fa7b7f86ea06749bfc9d10bb67b145140b)

Cq-Include-Trybots: master.tryserver.chromium.android:android_cronet_tester;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I6a80db88aafdf20c7abd3847404b818565681310
Reviewed-on: https://chromium-review.googlesource.com/748425
Reviewed-by: Zhongyi Shi <zhongyi@chromium.org>
Commit-Queue: Ryan Hamilton <rch@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#513105}
Reviewed-on: https://chromium-review.googlesource.com/749923
Reviewed-by: Ryan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/branch-heads/3163@{#1323}
Cr-Branched-From: ff259bab28b35d242e10186cd63af7ed404fae0d-refs/heads/master@{#488528}
[modify] https://crrev.com/34ae85f6bc596af851096f028aded7c09a44ead5/net/quic/core/quic_client_promised_info.cc
[modify] https://crrev.com/34ae85f6bc596af851096f028aded7c09a44ead5/net/quic/core/quic_client_promised_info_test.cc

Project Member

Comment 31 by sheriffbot@chromium.org, Nov 2 2017

Labels: -M-61
Project Member

Comment 32 by sheriffbot@chromium.org, Nov 2 2017

Status: Fixed (was: Assigned)
Please mark security bugs as fixed as soon as the fix lands, and before requesting merges. This update is based on the merge- labels applied to this issue. Please reopen if this update was incorrect.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Labels: CVE-2017-15398 Release-2-M62

Comment 34 by rch@chromium.org, Nov 2 2017

Cc: mef@chromium.org alexis.m...@intel.com
Cc: bradnelson@chromium.org
Labels: -Hotlist-Merge-Review
Labels: -ReleaseBlock-Stable
Project Member

Comment 38 by sheriffbot@chromium.org, Nov 3 2017

Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify

Comment 39 by rch@chromium.org, Nov 3 2017

Cc: justinho@google.com

Comment 40 by rch@chromium.org, Nov 3 2017

Cc: gboyer@google.com

Comment 41 by rch@chromium.org, Nov 3 2017

Cc: moshary@google.com
Cc: cbrubaker@google.com

Comment 43 by rch@chromium.org, Nov 3 2017

Cc: vasilvv@chromium.org
Labels: reward-topanel

Comment 45 by rch@chromium.org, Nov 7 2017

Cc: fil...@snapchat.com j...@snapchat.com
This bug was found with libFuzzer.

I'm contributing my fuzz target to the fuzzer program for those that are curious how I went about finding this: https://chromium-review.googlesource.com/c/chromium/src/+/753006

I should note that auditing could have easily found this bug, but I was trying to find bugs in many areas of code and fuzzing brings the cost of fully auditing a module down dramatically.
Labels: -reward-topanel reward-unpaid reward-10500
*** Boilerplate reminders! ***
Please do NOT publicly disclose details until a fix has been released to all our users. Early public disclosure may cancel the provisional reward. Also, please be considerate about disclosure when the bug affects a core library that may be used by other products. Please do NOT share this information with third parties who are not directly involved in fixing the bug. Doing so may cancel the provisional reward. Please be honest if you have already disclosed anything publicly or to third parties. Lastly, we understand that some of you are not interested in money. We offer the option to donate your reward to an eligible charity. If you prefer this option, let us know and we will also match your donation - subject to our discretion. Any rewards that are unclaimed after 12 months will be donated to a charity of our choosing.
*********************************
The VRP Panel awarded $10,500 for this bug, and mentioned that we'd be happy to look again if you submit a functional export for it.  Cheers!
Re #48: I believe "functional export" was meant to be "functional exploit"-- that is to say, a demonstration that results in the execution of arbitrary code in the browser process. https://www.google.com/about/appsecurity/chrome-rewards/index.html
Labels: -reward-unpaid reward-inprocess
Project Member

Comment 51 by sheriffbot@chromium.org, Dec 7 2017

Labels: -M-62
Project Member

Comment 52 by sheriffbot@chromium.org, Jan 25 2018

Labels: -M-63 M-64
Project Member

Comment 53 by sheriffbot@chromium.org, Feb 8 2018

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
Project Member

Comment 54 by sheriffbot@chromium.org, Mar 7 2018

Labels: -M-64 M-65
Project Member

Comment 55 by sheriffbot@chromium.org, Apr 19 2018

Labels: -M-65 M-66
Labels: CVE_description-missing
Project Member

Comment 57 by sheriffbot@chromium.org, May 30 2018

Labels: -M-66 M-67
Project Member

Comment 58 by sheriffbot@chromium.org, Jul 25

Labels: -M-67 Target-68 M-68
Project Member

Comment 59 by sheriffbot@chromium.org, Sep 5

Labels: -M-68 M-69 Target-69
Labels: -CVE_description-missing CVE_description-submitted
Project Member

Comment 61 by sheriffbot@chromium.org, Oct 17

Labels: -M-69 Target-70 M-70
Project Member

Comment 62 by sheriffbot@chromium.org, Dec 5

Labels: -M-70 Target-71 M-71

Sign in to add a comment