A Look into Netty’s Recent Security Update (CVE­-2015­-2156)

May 15, 2015

As part of our ongoing effort to secure our applications and contribute back to the community, the LinkedIn House Security team is often involved in security testing activities aimed at uncovering vulnerabilities in widely deployed open-source frameworks and applications.

During a recent assessment, we discovered a security flaw within Netty’s cookie parsing code which leads to a universal HttpOnly bypass in Play Framework and potentially other frameworks using Netty as a dependency. The issue has been fixed in Netty 3.9.8.Final, 3.10.3.FinalNetty 4.1.0.Beta5Netty 4.0.28.Final and Play Framework 2.3.9.

In this blog post, we explain the technical details of the vulnerability and provide information related to the patch issued by the Netty team. A library upgrade is required to fully mitigate the risk.

Description

According to RFC6265, each cookie begins with a name-­value ­pair, followed by zero or more attribute ­value pairs. In particular, the cookie’s value is defined by the following grammar:

cookie­value = *cookie­octet / ( DQUOTE *cookie­octet DQUOTE ) 
cookieoctet = %x21 / %x23­2B / %x2D­3A / %x3C­5B / %x5D­7E ; US­ASCII characters excluding CTLs, ; whitespace DQUOTE, comma, semicolon, ; and backslash 

In Netty’s implementation, an improperly terminated cookie value beginning with single­-quote​ or double-­quote was not ​being discarded. Instead, the parsing routine would consume the value till the end of the header or other special characters.

public Set<Cookie> decode(String header) {
	List<String> names = new ArrayList<String>(8);
	List<String> values = new ArrayList<String>(8);
	extractKeyValuePais(header, names, values);
	.....

private static void extractKeyValuePairs(
	final String header, final List<String> names, final List<String> values) {
	.....
	  if (c == ‘“’ || c == ‘\‘’) { //<--- If the first char is a QUOTE or DQUOTE, consume input till next QUOTE or DQUOTE
					     // NAME=”VALUE” or NAME=’VALUE’
		StringBuilder newValueBuf = new StringBuilder(header.length() – i);

As a result, the value of a cookie could potentially contain the entire ​Cookie​ header regardless of cookie’s flags.

The underlying vulnerability in Netty’s code can be easily reproduced with the following code:

Set<Cookie> cookies = CookieDecoder.decode(ADD_YOUR_COOKIES_STRING_HERE);
System.out.println(cookies);

Providing ​aaa=bbb;ccc=ddd​ as input, the method will correctly return an array with two elements (two cookies).

[aaa=bbb, ccc=ddd]

Instead, providing ​aaa=​'​bbb;ccc=ddd​ as input, the bug manifests itself returning a single element in the array.

[aaa=bbb;ccc=ddd]

Impact on Play Framework

At first sight, the bug doesn’t seem to have immediate security implications since the cookies are contained within the same HTTP request. However, under specific circumstances, this bug can be exploited to bypass ​HttpOnly​ flag restrictions as illustrated in the following example.

Play Framework implements CSRF protection using a cookie value (e.g. ​JSESSIONID)​ that is compared with a value submitted via HTTP POST parameters (e.g. ​csrfToken)​. The cookie is retrieved by server-side components and its value is typically injected as secret token within HTML forms and other elements. During the submission of the HTML form, both values are compared.

  • vulnerability screen shot

In the presence of the above mentioned vulnerability, a malformed cookie can be used to display the entire cookie header within the resulting HTML page.

  • Security vulnerability screen shot

In the default configuration of Play framework’s CSRF protection, this vulnerability can be abused to reflect sensitive cookies, even those protected by the HTTPOnly flag within the content of a web page.

From a web attack perspective, this is extremely interesting. In case of Cross-­Site­ Scripting (XSS) attacks or any vulnerability which allows to set arbitrary cookies, this bug can be leveraged to universally bypass the HttpOnly flag in all Play applications. I​f the ​HttpOnly ​flag is included in the HTTP response header, the cookie cannot be accessed through client-side script. In this case, since the cookie’s name-value is entirely included in the DOM, a malicious script can access the content without any restriction.

Next Steps

Many other projects using Netty may be vulnerable to similar "side­-effects" of the incorrect cookies parsing routine. We recommend that every project relying on Netty’s CookieDecoder method should mitigate the potential risk by upgrading to the latest version.

As a result of our disclosure, Netty’s cookie parsing code was patched and updated to be strictly RFC6265 compliant. Netty pull request related to this patch can be found at https://github.com/netty/netty/pull/3748.

Credits

This vulnerability was discovered by Roman Shafigullin, Luca Carettoni and Mukul Khullar and was reported to Play and Netty teams on 8th April 2015. CVE­-2015­-2156 has been assigned for this bug.

Topics