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

Leave a Reply