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):
[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 tagRecently 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