Closed Bug 1589609 Opened 9 months ago Closed 8 months ago

overwrite of response header under few circumstances with new version of mozila browser (misparsed header format), this can disable many security headers

Categories

(Core :: Networking: HTTP, defect, P2)

71 Branch
Unspecified
All
defect

Tracking

()

RESOLVED FIXED
mozilla72
Tracking Status
firefox72 --- fixed

People

(Reporter: rohanbirtia, Assigned: valentin)

Details

(Whiteboard: [reporter-external] [client-bounty-form] [verif?][necko-triaged])

Attachments

(5 files, 1 obsolete file)

Attached image new browser.png

New version of mozila include other header (like x-content-type-options) into x-frame-options header & it overwrites the x-frame-options header policy and makes it to

Server:Microsoft-IIS/8.5
X-Frame-Options:SAMEORIGIN X-Content-Type-Options: nosniff *note here*
X-Powered-By ASP.NET

resulting no click-jacking protection bypass for same cases.

I have tested with old browsers which differentiate between X-Frame-Options and X-Content-Type-Options.
attached screenshot for both browsers.

Flags: sec-bounty?
Attached image old_browser.png

Please provide a link to a public testcase that sends the headers that you believe are being misparsed.

Group: firefox-core-security → network-core-security
Type: task → defect
Component: Security → Networking: HTTP
Flags: needinfo?(rohanbirtia)
Product: Firefox → Core
Summary: defeating click jacking protection under few circumstances with new version of mozila browser. → defeating click jacking protection under few circumstances with new version of mozila browser (misparsed header format)
Flags: needinfo?(rohanbirtia)
OS: Unspecified → All
Priority: -- → P2
Summary: defeating click jacking protection under few circumstances with new version of mozila browser (misparsed header format) → overwrite of response header under few circumstances with new version of mozila browser (misparsed header format), this can disable many security headers
Version: unspecified → 71 Branch

Hi team,
I figured out why this happened. Attached a video poc of how it works on that site.

Even if I give the site you wouldn't be able to access because it's an internal application & it'll take time to set up the same server config. but I explained in the video how you can replicate.

Basically, if a response header contains white spaces (any number of ) new mozila doesn't parse it as other headers, it continues from the previous header. Which other browser pareses perfectly and differentiate between other headers. It can be any response header.

As you could see from that internal website screenshot, it can disable many security features.

Attached video video.mp4

attached poc for why and how the bug works

Please do not alter the priority field.

Priority: P2 → --

This looks like it's due to line-folding per rfc7230:

   Historically, HTTP header field values could be extended over
   multiple lines by preceding each extra line with at least one space
   or horizontal tab (obs-fold).  This specification deprecates such
   line folding except within the message/http media type
   (Section 8.3.1).  A sender MUST NOT generate a message that includes
   line folding (i.e., that has any field-value that contains a match to
   the obs-fold rule) unless the message is intended for packaging
   within the message/http media type.

I don't know what, if anything has changed recently in this space. A bugzilla search doesn't turn up anything. Valentin, maybe you know?

If other browsers really don't do it (which is hard to quickly verify without a public testcase) then perhaps we should follow suit for web compat's sake.

Flags: needinfo?(valentin.gosu)
Attached file test.http

I was able to reproduce this bug in Chrome too.
Download this file, then run the following command:
while true; do cat test.http | nc -l 8000 -q 0; done then go to http://localhost:8000

I have no idea why the reporter says this doesn't reproduce in Fx56 - I managed to do it with this small test case and with a xpcshell-test.

For what it's worth, the bug can be fixed at this line, by removing the ' ' and '\t' cases.

Also relevant to the conversation: https://lists.w3.org/Archives/Public/ietf-http-wg/2013JanMar/0249.html
I don't know if we have other reports of this issue, but it seems we should fix it.

Flags: needinfo?(valentin.gosu)
Flags: needinfo?(nhnguyen)

PS. I don't exactly see how this would be exploitable, unless a server adds whitespace by mistake in which case it's pretty much their fault.

Hi valentin,
There seems to cache issue in that application that's why i was not able to reproduce in chrome, sorry about that. Seems like the application team tried to pass the buck to security team.

Thanks.

So, on a second reading of the rfc I noticed this:

   A user agent that receives an obs-fold in a response message that is
   not within a message/http container MUST replace each received
   obs-fold with one or more SP octets prior to interpreting the field
   value.

So, technically this folding is still allowed - the condition is to replace CRLF 1*( SP / HTAB ) with one or more spaces - which we don't currently do,.
The github fetch polyfill also implements this
So this is probably not a sec bug.

Flags: needinfo?(nhnguyen)
Group: network-core-security
Assignee: nobody → juhsu
Priority: -- → P2
Whiteboard: [reporter-external] [client-bounty-form] [verif?] → [reporter-external] [client-bounty-form] [verif?][necko-triaged]

Correct me if I'm wrong.

rfc7230 3. Message Format

     HTTP-message   = start-line
                      *( header-field CRLF )
                      CRLF
                      [ message-body ]

where

     start-line     = request-line / status-line
     request-line   = method SP request-target SP HTTP-version CRLF
     status-line = HTTP-version SP status-code SP reason-phrase CRLF

==> start-line always end with CRLF
==> header-filed always next to CRLF

And lets take a look at header-field

     header-field   = field-name ":" OWS field-value OWS

     field-name     = token
     field-value    = *( field-content / obs-fold )
     field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
     field-vchar    = VCHAR / obs-text

     obs-fold       = CRLF 1*( SP / HTAB )
                    ; obsolete line folding
                    ; see Section 3.2.4

Note that obs-fold is only taken into account for field-value, not field-name.
token is defined in RFC 2616 which excludes SP

       token          = 1*<any CHAR except CTLs or separators>
       separators     = "(" | ")" | "<" | ">" | "@"
                      | "," | ";" | ":" | "\" | <">
                      | "/" | "[" | "]" | "?" | "="
                      | "{" | "}" | SP | HT

In any case, each header line should not start with space.

INVALID, but I can write a test to assert this.

Attachment #9105415 - Attachment is obsolete: true
Pushed by valentin.gosu@gmail.com:
https://hg.mozilla.org/integration/autoland/rev/b0e8a5be4d2c
Add unit test for obs-fold header parsing r=JuniorHsu
Status: UNCONFIRMED → RESOLVED
Closed: 8 months ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla72

Note that the patch didn't change any Firefox behaviour, it just added a test that we correctly implement the obs-fold scenario.

Assignee: juhsu → valentin.gosu

Hi,
Just for curiosity may I know why this bug id is publically accessible. I still believe it is a security issue as if CRLF injection is possible and the attacker is not able to inject new headers, he can disable security headers.

(In reply to rohanbirtia from comment #17)

Hi,
Just for curiosity may I know why this bug id is publically accessible. I still believe it is a security issue as if CRLF injection is possible and the attacker is not able to inject new headers, he can disable security headers.

It's not clear to me how an attacker could perform such injection.
Could you explain how that scenario would work? Is it a man in the middle for unsecure HTTP/compromised server with HTTPS/something else?

Flags: sec-bounty? → sec-bounty-

(In reply to Valentin Gosu [:valentin] (he/him) from comment #18)

(In reply to rohanbirtia from comment #17)

Hi,
Just for curiosity may I know why this bug id is publically accessible. I still believe it is a security issue as if CRLF injection is possible and the attacker is not able to inject new headers, he can disable security headers.

It's not clear to me how an attacker could perform such injection.
Could you explain how that scenario would work? Is it a man in the middle for unsecure HTTP/compromised server with HTTPS/something else?

Nothing with related HTTP or HTTPS , in some cases like CRLF injection it works like this characters from HTTP request directly reflects into response header. So most of the WAF and application block certain characters like %0a %0d. But although these characters are blocked now using our vulnerability attacker can disable certain headers and escalate.

Want to add here is this example (facebook XSS using CRLF) [https://habr.com/en/company/pt/blog/247709/], If the Researcher would have none this vulnerability instead of creating new header named X-XSS-Protection:0 he could have just overwritten the header.

from the same researcher and my friend bobrov https://hackerone.com/reports/66386 , As you can see to escalate CRLF he used https://www.example.com/xxcrlftest%0aSet-Cookie:test=test3;domain=.example.com, with our vulnerability he could have chained to more severe attack just by adding whitespace.

In our daily testing we face a lot of situation like this where only certain characters were reflected in response, this would be added advantage for attacker.

You need to log in before you can comment on or make changes to this bug.