Tuesday, 22 December 2015

Small subgroup attack in Mozilla NSS

tl;dr While the TLS servers attacks has been pretty much studied and fixed (see e.g. https://www.secure-resumption.com/ and https://weakdh.org/) the situation with the TLS clients is (was) not ideal and can be improved. Here I report a Small subgroup attack for TLS clients that I performed against various browsers and reported.

Whoever reads this blog is used to read about OAuth .
For once (and maybe more in the future) let's hijack the usual topic and let's talk about my new "passion" : TLS in particular Diffie–Hellman (DH from now on).

Now, before to start I need to clarify one thing IANAC (I am not a cryptographer) so I might likely end up writing a bunch of mistakes in this blog post...

Diffie-Hellman is used in SSL/TLS, as "ephemeral Diffie-Hellman" (EDH) and it is probably going to be kill soonish (or at least is the intent of Google Chrome). FWIW I personally agree with this unless EDH implements the Negotiated Finite Field specification.

Now in the last years there were at least a couple of issue that affected EDH:
What I am going to describe here is by far less severe that the issues above.  Indeed has been rated by Mozilla NSS as security moderate and Google Chrome did not consider harmful at all (and since Adam Langley is one of the people that is on this side I got to agree with him :)  ).

But here the details:

When using TLS_DHE_RSA_WITH_AES_128_CBC_SHA Firefox/Chrome doesn't accept degenerate public key of value 0,1 and -1 since this key lead to pms that is {0,1, -1}.
This (the -1 case) is probably a consequence of CVE-2014-1491 (raised as part of the Triple Handshake Attack ).

I would refer to the classic  Diffie Hellman nomenclature
  •  p as the prime number
  • g the generator with order p-1 = q
  • y public key
  • x private key


If (p-1)/4  = 0 (mod p) then if I choose my private key x = (p-1)/4 then my public key
y = g^x will generates a prime-order subgroup of size 4.

This means that Mozilla/Chrome will agree on a pms = 1 one time out of 4.

The issue

I set up a server with

p = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084241
g = 3
q =1

and TLS_DHE_RSA_WITH_AES_128_CBC_SHA as cipher.

During the negotiation with Chrome I always choose

x= (p-1)/4 = 3351951982485649274893506249551461531869841455148098344430890360930441007518386744200468574541725856922507964546621512713438470702986642486608412251521060

and pass

y = 11130333445084706427994000041243435077443611277989851635896953056790400956946719341695219235480436483595595868058263313228038179294276393680262837344694991

Chrome/Firefox will happily "agree" on those 4 pms
  • 1
  • 2277474484857890671580024956962411050035754542602541741826608386931363073126827635106655062686466944094435990128222737625715703517670176266170811661389250
  • 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084240
  • 11130333445084706427994000041243435077443611277989851635896953056790400956946719341695219235480436483595595868058263313228038179294276393680262837344694991

Of course the "worse" one is 1 and happens to be 1 time out of 4 (according to Adam Langley though "here's nothing special about sending an odd DH value, it could equally well make its DH private key equal to 42"). So not big deal :(

Just for the record even the easier suggestion given in [1] aka

"Make sure that g^x,g^y and g^xy do not equal to 1"

 is not followed and this happens with very high probability (25%)

The Summary

[1] http://crypto.cs.mcgill.ca/~stiglic/Papers/dhfull.pdf

Thursday, 17 December 2015

Top 10 OAuth 2 Implementation Vulnerabilities

Some time ago I posted a blogpost abut  Top 5 OAuth 2 Implementation Vulnerabilities.
This week I have extended the list while presenting Top X OAuth 2 Hacks at OWASP Switzerland.

This blog post (like the presentation) is just a collection of interesting attack OAuth related.

#10 The Postman Always Rings Twice 

I have introduced this 'attack' in last year post . This is for provider implementer, it is not extremely severe but, hey, is better to follow the spec. Specifically

The client MUST NOT use the authorization code  more than once.  If an authorization code is used more than once, the authorization server MUST deny the request and SHOULD revoke (when possible) all tokens previously issued based on that authorization code.

It turned out that even Facebook and Google did it wrong... :)

#9 Match Point

To all OAuth Providers be sure to follow section 4.1.3 of the spec in particular

...if the "redirect_uri" parameter was included in the initial authorization request as described in Section 4.1.1, and if included ensure that their values are identical.

Should you fail to do it, this in combination with Lassie Come Home below is game over (even for implementer that support only the Authorization Code Grant flow).

#8 Open redirect in rfc6749 

If you want to implent OAuth Authorization Server and  follow verbatim the OAuth core spec you might end up having an Open Redirect. Full story here . Interesting attack here .

#7 Native apps - Which OAuth flow ?

In a nutshell

  • It is NOT recommended that native applications use the implicit flow.
  • Native clients CAN NOT protect a client_secret unless it is configured at runtime as in the dynamic registration case (RFC 7591).
If you do not follow this suggestions then you risk this.

#6 Cross-site request forgery for OAuth Clients

Defined  the the Most Common OAuth2 Vulnerability. So do you the state anti CSRF parameter, as long as you use the right library to check and not a broken one :)

#5 Cross-site request forgery for Authorization Servers

As per any other website part is important to not forget Cross Site Request Forgery aka CSRF protection in your OAuth provider impelemtation. Some examples are:

#4 On Bearer Tokens

DO NOT  (if you can avoid) pass the access_token as a URI parameter a la

GET /resource?access_token=mF_9.B5f-4.1Jq HTTP/1.1                  
Host: server.example.com


#3 The Devil Wears Prada

 If you are an OAuth client that use OAuth for authentication (do NOT). If you absolutely have to, you'd better read User Authentication with OAuth 2.0 . Specially if you are using the OAuth Implicit Grant flow (aka Client side).
More about the topic in here and here

#2 Lassie Come Home for OAuth clients

If you are building an OAuth client,  
Thou shall register a redirect_uri as much as specific as you can

#1 Lassie Come Home for Authorization Server

 ....and the winner is (again) 'Lassie Come Home'. Well this is hell of a danger.
There are way too many example of provider vulnerable to this attack. Just listing few here:

At least the mitigation for this issue is damn simple:  use exact matching against registered redirect uri to validate the redirect_uri parameter

BTW the slides are here.

If you like OAuth 2.0 and/or you want to know more about it here you can find a book on OAuth that Justin Richer and myself have been writing on the subject.


Monday, 7 December 2015

A Quick Glance at Modern Browsers's Protection Part #1

tl;dr in this blog post we are going to give a look at modern browsers's protection with some hands on example available at https://github.com/asanso/browsers-security and deployed in Heroku. This blog post is NOT about Same-origin policy


In this blog post we are going to give a look at modern browsers's protection. More specifically if you are designing a REST API where the result response is driven by some user input, then why not have some help from the browser rather than brewing some ad hoc protection?
I am going to provide some demo deployed in Heroku .
If you prefer running them on your machine you might want to clone  https://github.com/asanso/browsers-security and drill down into the specific example.

Mind your content type

By definition Content-Type entity-header field indicates the media type of the entity-body sent to the recipient or, in the case of the HEAD method, the media type that would have been sent had the request been a GET
It turns out that returning the proper Content-Type might save a lot of headache. 

Or from your browsers-security check out:
So lets dig the response using curl:

curl -v -L "https://mysterious-ocean-4724.herokuapp.com/?name=<script>alert(document.domain)</script>"

< HTTP/1.1 200 OK
* Server Cowboy is not blacklisted
< Server: Cowboy
< Connection: keep-alive
< X-Powered-By: Express
< Content-Type: text/html; charset=utf-8
< Content-Length: 42
< Etag: W/"2a-QK3v/EQbwe/c0QdPJrXydw"
< Date: Wed, 02 Dec 2015 15:16:31 GMT
< Via: 1.1 vegur

{"helloWorld": "<script>alert(

As you can see we are returning some JSON payload in the response but using the "wrong" Content-Type (aka text/html). This in combination with a malicious input provided by an attacker will make the browser to happily execute the provided javascript snippet.
Now of course output sanitization (this is always good BTW) would have stopped this attack but this would have required some effort. From the other hand just returning the right Content-Type (application/json in this example ) will make the browser displaying the JSON text content as in this example


curl -v -L "https://mysterious-ocean-4724.herokuapp.com/?surname=<script>alert(document.domain)</script>" 

< HTTP/1.1 200 OK
* Server Cowboy is not blacklisted
< Server: Cowboy
< Connection: keep-alive
< X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
< Content-Length: 56
< Etag: W/"38-AEX4mYlsmzOHSw8oOicxiQ"
< Date: Mon, 07 Dec 2015 09:39:53 GMT
< Via: 1.1 vegur

Bonus Part:  
The examples above where targetting a stored XSS. Those are cross browsers and if successful (namley some stored javascript is displayed in some not sanitized output) every browser will happiliy execute the javascript.  For  reflected XSS (where the input is bounced directly in the output) some browsers (Chrome, Safari, IE ) ship with an XSS filter. E.g. try to hit the follow link with Google Chrome

has the result 

The XSS Auditor refused to execute a script in 'https://mysterious-ocean-4724.herokuapp.com/?title=%3Cscript%3Ealert%28document.domain%29%3C/script%3E' because its source code was found within the request. 

and the XSS is then stopped by the browser. From the other hand Firefox would still be vulnerable.

Re-mind your content type

As returning a "wrong" content type you might imagine that not returning a Content-Type AT ALL is NOT a so great idea :) Indeed there are some browsers (did I say IE :)?) that trying to be extra clever and try to  intelligently interpret the response content in order to guess the right Content-Type. In the netsec jargon this is call sniffing. But let's the example talking on its own, using IE ONLY


Again if you prefer running in local then clone https://github.com/asanso/browsers-security/tree/master/noContentType

Trying to inspect the response we can see the total lack of content type:

curl -v -L "https://protected-garden-1595.herokuapp.com?name=<script>alert(document.domain)</script>"

< HTTP/1.1 200 OK
* Server Cowboy is not blacklisted
< Server: Cowboy
< Connection: keep-alive
< Date: Mon, 07 Dec 2015 10:52:54 GMT
< Content-Length: 51
< Via: 1.1 vegur
Hello World <script>alert(document.domain)</script>

The solution is obviously is to return the correct  Content-Type hence

TIL: mind you Content-Type

Coming soon...

This concludes the part #1. If you like this stuff you might watch this space for:
  • more about Content-Type
  • nosniff 
  • X-XSS-Protection
  • Content-Disposition
  • Content Security Policy (CSP)
  • Cross-origin resource sharing (CORS)
  • HTTP Strict Transport Security (HSTS)
  • Subresource Integrity (SRI)