[code autolinks=”false”]
#####################################################################
# Unified diff (patch file) to modify Dionaea’s mysql.py module #
# to enable it to capture binaries from the cna12 MySQL attacks #
# #
# Application instructions #
# [from Dionaea’s top level source directory] #
# cd ./modules/python/scripts/mysql #
# patch -l < dionaea-mysql.py.diff #
# #
# dionaea-mysql.py.diff v2013.04.16 #
# http://malwaremusings.com/supporting-files/dionaea-mysql-py-diff/ #
#####################################################################
— mysql.py.dist 2012-11-24 11:27:00.000000000 +1100
+++ mysql.py 2013-01-31 00:01:41.323397721 +1100
@@ -30,12 +30,15 @@
from .include.packets import *
import logging
import sqlite3
+import tempfile
logger = logging.getLogger(‘mysqld’)
class mysqld(connection):
def __init__ (self):
connection.__init__(self,"tcp")
+ self.autocommit = 1
+
def handle_established(self):
self.config = g_dionaea.config()[‘modules’][‘python’][‘mysql’][‘databases’]
@@ -89,8 +92,51 @@
def _handle_COM_QUERY(self, p):
r = None
– if p.Query.startswith(b"SET "):
– r = MySQL_Result_OK(Message="#2")
+ #logger.info("Q: %s\n" % p.Query)
+ if p.Query.upper().startswith(b"SET "):
+ #r = MySQL_Result_OK(Message="#2")
+
+ if (p.Query.upper() == b’SET AUTOCOMMIT=0′):
+ logger.info(" Setting autocommit to 0")
+ self.autocommit = 0
+ r = MySQL_Result_OK(ServerStatus = 0x000)
+ else:
+ # check for 0x4D5A
+ qry = p.Query.lower()
+ try:
+ # strip white space
+ qry = qry.translate(None,b"\r\n\t ")
+ except Exception as e:
+ logger.info(e)
+
+ # convert it to a string so .find() will work
+ qry = str(qry)
+ #logger.info("q: %s\n" % qry)
+ peidx = qry.find("0x4d5a")
+
+ if (peidx >= 0):
+ # extract PE file
+ idx = peidx + 2
+ while ((qry[idx] in "0123456789abcdef\r\n\t ") and (idx < len(qry))):
+ #logger.info("[%d]: %c" % (idx,qry[idx]))
+ idx = idx + 1
+ logger.info("pe @ %d – %d" % (peidx + 2,idx))
+ hexstr = qry[peidx + 2:idx]
+ #logger.info("PE: %s\n" % hexstr)
+ try:
+ f = tempfile.NamedTemporaryFile(delete = False,prefix = "mysql-",suffix = ".tmp",dir = g_dionaea.config()[‘downloads’][‘dir’])
+ f.write(bytes.fromhex(hexstr))
+ f.close()
+ except Exception as e:
+ logger.info(e)
+
+ i = incident("dionaea.download.complete")
+ i.path = f.name
+ i.url = "hex://" + self.remote.host
+ i.con = self
+ i.report()
+
+ r = MySQL_Result_OK()
elif p.Query == b’select @@version_comment limit 1′:
r = [MySQL_Result_Header(FieldCount=1),
@@ -158,6 +204,57 @@
x = MySQL_Result_Row_Data(ColumnValues=[res[name] for name in names])
r.append(x)
r.append(MySQL_Result_EOF(ServerStatus=0x002))
+ elif p.Query.upper() == b’SELECT VERSION()’:
+ logger.info(" EOF with autocommit: %d" % self.autocommit)
+ r = [MySQL_Result_Header(FieldCount = 1),
+
+ MySQL_Result_Field(Catalog=’def’,
+ Database=b”,
+ Table=b”,
+ ORGTable=b”,
+ Name=b’VERSION()’,
+ ORGName=b”,
+ CharSet=33, # utf8, collate utf8_general_ci
+ Length=8,
+ Type=FIELD_TYPE_VAR_STRING,
+ Flags=FLAG_NOT_NULL,
+ Decimals=31),
+ MySQL_Result_EOF(ServerStatus=self.autocommit * 0x002)]
+
+ r.append(MySQL_Result_Row_Data(ColumnValues=["5.5.28-1"]))
+ r.append(MySQL_Result_EOF(ServerStatus=self.autocommit * 0x002))
+ elif p.Query.upper().startswith(b"SELECT XPDL3("):
+ qry = p.Query.lower()
+ try:
+ # strip white space
+ qry = qry.translate(None,b"\r\n\t ")
+ except Exception as e:
+ logger.info(e)
+
+ # convert it to a string so .find() will work
+ qry = str(qry)
+ #logger.info("q: %s\n" % qry)
+
+ urlidx = -1
+ httpidx = qry.find("’http:")
+ httpsidx = qry.find("’https:")
+ if (httpidx >= 0):
+ urlidx = httpidx + 1
+ elif (httpsidx >= 0):
+ urlidx = httpsidx + 1
+
+ if (urlidx >= 0):
+ urlend = qry.find("’",urlidx)
+ if (urlend >= 0):
+ url = qry[urlidx:urlend]
+ logger.info("U: %s\n" % url)
+
+ i = incident("dionaea.download.offer")
+ i.con = self
+ i.url = url
+ i.report()
+
+ r = MySQL_Result_OK(Message=’#ok…(c:\isetup.exe) portnumber (3389) osversion (WinXP)’,ServerStatus=self.autocommit * 0x002)
else:
p.show()
try:
[/code]
Pingback: Capturing the cna12 MySQL Attacks with Dionaea | Malware Musings
patch < dionaea-mysql.py.diff
patching file mysql.py
Hunk #1 FAILED at 30.
patch: **** malformed patch at line 85: @@ -158,6 +204,57 @@
Patch isnt working.
Hi Marcelo,
Thanks for highlighting this and apologies for the delay, but I’d over estimated the complexity of the problem and the amount of work involved and hence the amount of time required to fix it.
I’d assumed that the Dionaea code had changed and that I needed to find some time to go through and update my changes, when in fact my original copy of the patch still works with the latest Dionaea code.
Yesterday, I went back to trying to get my HoneyDrive3 installation to a point where I can use it to replace my existing honeypot set-up, and naturally wanted to modify the Dionaea installation there-on to capture these MySQL attacks. So I thought that that would be a good time to test this patch.
You’re right. A simple copy and paste version of the patch from my blog page will fail to apply. There are two reasons. One, there is a missing blank line around line 85, for some reason. Two, a copy and paste means that you end up with a series of spaces where there once were tabs.
I’ve updated the copy on my blog page to include the blank line, so it is now a correctly formatted patch at least. However, the second problem still remains. You can get around this by using the ‘-l’ option when running ‘patch’. The ‘-l’ (lower case letter) option tells ‘patch’ to ignore differences in white space.
However, I’d rather have a way for readers to get a byte-for-byte copy of scripts/patches as I’ve written them, rather than as they end up after being copied and pasted. Especially when indentation (leading white space) matters when it comes to Python scripts.
So, I have created a sub-page of this one which simply contains a base64 encoded version of the patch shown on this page. You can copy and paste the base64 version, and then simply decode it using any of the base64 decoding utilities (‘openssl’ and ‘uudeview’ for instance).
Unfortunately, if you’re using Windows, you may be a bit pushed for native base64 decoding utilities, although a quick Internet search shows a number of downloadable ones. I’ve also just thrown together a Python script (http://malwaremusings.com/supporting-files/b64decode-py/) which will do base64 decoding. Base64 encoding that will create a chicken-and-egg type situation though.
Musingly,
Karl.