Closed Bug 1194820 (CVE-2015-7219) Opened 9 years ago Closed 9 years ago

Firefox HTTP2 Malformed PushPromise Underflow DoS


(Core :: Networking: HTTP, defect)

39 Branch
Not set



Tracking Status
firefox42 --- wontfix
firefox43 --- fixed
firefox-esr38 --- wontfix


(Reporter: c0nrad, Assigned: mcmanus)


(Keywords: csectype-dos, sec-low, Whiteboard: [post-critsmash-triage][adv-main43+])


(1 file)

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36

Steps to reproduce:

# Firefox HTTP2 Malformed PushPromise Underflow DoS

## Overview
A malformed HTTP2 PushPromse frame is sent to the browser. The length of the decompressed buffer is miscalculated an underflow occurs. This causes an nsCString to try to allocate nearly 2^32 bytes of memory. This is greater than firefox allows and an assert is tripped.

## Walkthrough

On line 1634 of Http2Session.cpp, a call is made to append the decompressed frame onto a decompressed buffer. 

self->mDecompressBuffer.Append(self->mInputFrameBuffer + kFrameHeaderBytes + paddingControlBytes + promiseLen,
         self->mInputFrameDataSize - paddingControlBytes - promiseLen - paddingLength);

The values and types for the PoC are:

self->mDecompressBuffer.Append(nsAutoArrayPtr<char>(ptr) + uint_8(9) + uint8_t(1) + uint32_t(4), uint32_t(76) - uint8_t(1) - uint32_t(4) - uint16_t(75));

The second argument is casted to a size_type (uint32), and the underflow occurs. The resulting value is 4294967292.

A bunch of string checks are then performed to make sure the append is sane. Eventually in nsTSubstring.cpp:45 MutatePrep is called with:

MutatePrep(this=0x00000xxxx, aCapacity=4294967292, aOldData=0x00000xxxxx, aOldFlags=0x00000xxxxxxx).

In the function, kMaxCapacity for a string is determined to be:

const size_type kMaxCapacity = (size_type(-1) / 2 - sizeof(nsStringBuffer)) / sizeof(char_type) - 2;
// kMaxCapacity = 2147483637

kMaxCapacity is then compared to our capacity (4294967292). Since the capacity exceds the max allowed, an error is thrown on line 531 of nsTSubstring.cpp.

AllocFailed(Length() - aCutLength + 1)

## Tested on 

Firefox 39.0. MacOS
42.0a1 (2015-07-21) MacOS

## PoC
Code can be found here:

To use:
Extract the file and the certs
$ go run firefoxHeaderPoc.go
$ ./firefox https://localhost:8000

## Author

Stuart Larsen
Yahoo! Pentest Team
Component: Untriaged → Networking: HTTP
Flags: needinfo?(mcmanus)
Product: Firefox → Core
Attachment #8649463 - Flags: review?(hurley)
Assignee: nobody → mcmanus
Ever confirmed: true
patch passes the PoC included in bug and regression xpcshell h2 testing run locally.
Flags: needinfo?(mcmanus)
Attachment #8649463 - Flags: review?(hurley) → review+
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla43
Group: core-security → core-security-release
Comment on attachment 8649463 [details] [diff] [review]
h2 push promise padding handling

[Approval Request Comment]
If this is not a sec:{high,crit} bug, please state case for ESR consideration: the best case for consideration is that this bug is going to be presented on at an upcoming security conference ( 
User impact if declined: possible DoS
Fix Landed on Version: 43
Risk to taking this patch (and alternatives if risky): low
String or UUID changes made by this patch: none

See for more info.
Attachment #8649463 - Flags: approval-mozilla-esr38?
Comment on attachment 8649463 [details] [diff] [review]
h2 push promise padding handling

As it doesn't match the ESR criteria (sec-high or critical), not taking it.
Attachment #8649463 - Flags: approval-mozilla-esr38? → approval-mozilla-esr38-
Whiteboard: [post-critsmash-triage]
Whiteboard: [post-critsmash-triage] → [post-critsmash-triage][adv-main43+]
Alias: CVE-2015-7219
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.