|
|
.. _filemd5-listing:
|
|
|
|
|
|
Filemd5 and white or black listing with MD5 hashes
|
|
|
==================================================
|
|
|
|
|
|
|
|
|
|
|
|
This guide will show you how to set up a white/black MD5 listing using latest Suricata on Ubuntu LTS 12.04 64 bit
|
|
|
and a file containing 87 million MD5s - white list.
|
|
|
|
|
|
|
|
|
In this set up we had/did the following :
|
|
|
|
|
|
1. A Suricata installation with :doc:`md5` enabled.
|
|
|
2. We start Suricata with about 4.5K rules and the MD5 white list file containing 87 million MD5 entries.
|
|
|
3. We have a 9.5Gb of traffic.
|
|
|
4. We have the following set up:
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
CPU: One Intel(R) Xeon(R) CPU E5-2680 0 @ 2.70GHz (16 cores counting Hyperthreading)
|
|
|
Memory: 32Gb
|
|
|
capture NIC: Intel 82599EB 10-Gigabit SFI/SFP+
|
|
|
|
|
|
|
|
|
|
|
|
You need to get the white list file containing MD5s from here - http://www.nsrl.nist.gov/Downloads.htm
|
|
|
This is an official database containing SHA-1 and MD5s for files that are " traceable ".
|
|
|
For example after you download and unzip (I used the Combo DVD link) you would get a file like so:
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
|
|
|
"SHA-1","MD5","CRC32","FileName","FileSize","ProductCode","OpSystemCode","SpecialCode"
|
|
|
"000000206738748EDD92C4E3D2E823896700F849","392126E756571EBF112CB1C1CDEDF926","EBD105A0","I05002T2.PFB",98865,3095,"WIN",""
|
|
|
"0000004DA6391F7F5D2F7FCCF36CEBDA60C6EA02","0E53C14A3E48D94FF596A2824307B492","AA6A7B16","00br2026.gif",2226,228,"WIN",""
|
|
|
"000000A9E47BD385A0A3685AA12C2DB6FD727A20","176308F27DD52890F013A3FD80F92E51","D749B562","femvo523.wav",42748,4887,"MacOSX",""
|
|
|
"00000142988AFA836117B1B572FAE4713F200567","9B3702B0E788C6D62996392FE3C9786A","05E566DF","J0180794.JPG",32768,16848,"358",""
|
|
|
"00000142988AFA836117B1B572FAE4713F200567","9B3702B0E788C6D62996392FE3C9786A","05E566DF","J0180794.JPG",32768,18266,"358",""
|
|
|
"00000142988AFA836117B1B572FAE4713F200567","9B3702B0E788C6D62996392FE3C9786A","05E566DF","J0180794.JPG",32768,20316,"358",""
|
|
|
"00000142988AFA836117B1B572FAE4713F200567","9B3702B0E788C6D62996392FE3C9786A","05E566DF","J0180794.JPG",32768,20401,"358",""
|
|
|
"00000142988AFA836117B1B572FAE4713F200567","9B3702B0E788C6D62996392FE3C9786A","05E566DF","J0180794.JPG",32768,2322,"WIN",""
|
|
|
"00000142988AFA836117B1B572FAE4713F200567","9B3702B0E788C6D62996392FE3C9786A","05E566DF","J0180794.JPG",32768,23822,"358",""
|
|
|
|
|
|
|
|
|
The file contains 87 million entries/lines, each line having
|
|
|
"SHA-1","MD5","CRC32","FileName","FileSize","ProductCode","OpSystemCode","SpecialCode"
|
|
|
of a traceable file.
|
|
|
|
|
|
You can use the Linux "cut" utility to make this file into only a MD5 file - have only the MD5 check sums (second row) - which is what we need.
|
|
|
Here is what you can do:
|
|
|
|
|
|
Download the ComboDVD - http://www.nsrl.nist.gov/RDS/rds_2.47/RDS_247.iso
|
|
|
|
|
|
unzip/tar, then
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
cat NSRFile.txt | more
|
|
|
|
|
|
would be able to see the beginning of the file and get an idea of what does it contain.(shown above)
|
|
|
**NOTE – this is a 10GB file, make sure you have the space!**
|
|
|
|
|
|
the MD5 column ... should start with "MD5"
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
sudo cut -d'"' -f4 NSRFile.txt >> MD5.txt
|
|
|
|
|
|
and you have only MD5s ...but still with "MD5" on top
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
sed -i '1d' MD5.txt
|
|
|
|
|
|
wait for a while
|
|
|
check the file
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
wc -l MD5.txt
|
|
|
|
|
|
wait for about 2-3 min
|
|
|
|
|
|
should be about 87Mil something md5s , one per line
|
|
|
**NOTE:**
|
|
|
You can also import the file into a MySQL database, if you would like:
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
mysql> create user 'filejson'@'localhost' IDENTIFIED BY 'PASSWORD123';
|
|
|
Query OK, 0 rows affected (0.00 sec)
|
|
|
|
|
|
mysql>create database filejsondb;
|
|
|
mysql> grant all privileges on filejsondb.* to 'filejson'@'localhost' with grant option;
|
|
|
mysql> flush privileges;
|
|
|
mysql> use filejsondb;
|
|
|
|
|
|
Then:
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
CREATE TABLE MD5(md5_whitelist VARCHAR(32));
|
|
|
|
|
|
The trick here for the import is that **the table name and the file name MUST be the same** - aka MySQL table "MD5" and the file is called MD5.txt!
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
sudo mysqlimport -u root -p --local filejsondb MD5.txt
|
|
|
|
|
|
Where "filejsondb" is the name of the database.
|
|
|
|
|
|
|
|
|
|
|
|
So , here is how we did it ....
|
|
|
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
pevman@suricata:~$ ls -lh /etc/suricata/et-config/MD5_NSRFile.txt
|
|
|
-rw-r--r-- 1 root root 2.7G Aug 29 00:35 /etc/suricata/et-config/MD5_NSRFile.txt
|
|
|
|
|
|
pevman@suricata:~$ wc -l /etc/suricata/et-config/MD5_NSRFile.txt
|
|
|
87345542 /etc/suricata/et-config/MD5_NSRFile.txt
|
|
|
pevman@suricata:~$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
pevman@suricata:~$ sudo tcpstat -i eth3
|
|
|
Time:1346241952 n=6664547 avg=898.01 stddev=757.68 bps=9575769952.00
|
|
|
Time:1346241957 n=6670750 avg=897.22 stddev=754.07 bps=9576254160.00
|
|
|
Time:1346241962 n=6626520 avg=903.62 stddev=747.26 bps=9580577822.40
|
|
|
Time:1346241967 n=6685956 avg=895.15 stddev=749.34 bps=9575883715.20
|
|
|
Time:1346241972 n=6712481 avg=891.53 stddev=747.34 bps=9575027134.40
|
|
|
Time:1346241977 n=6696189 avg=893.82 stddev=746.62 bps=9576294273.60
|
|
|
Time:1346241982 n=6681826 avg=895.75 stddev=749.67 bps=9576376033.60
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
pevman@suricata:~$ suricata --build-info
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:539) <Info> (SCPrintBuildInfo) -- This is Suricata version 1.4dev (rev 75af345)
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:612) <Info> (SCPrintBuildInfo) -- Features: PCAP_SET_BUFF LIBPCAP_VERSION_MAJOR=1 AF_PACKET HAVE_PACKET_FANOUT LIBCAP_NG LIBNET1.1 HAVE_HTP_URI_NORMALIZE_HOOK HAVE_HTP_TX_GET_RESPONSE_HEADERS_RAW HAVE_NSS
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:626) <Info> (SCPrintBuildInfo) -- 64-bits, Little-endian architecture
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:628) <Info> (SCPrintBuildInfo) -- GCC version 4.6.3, C version 199901
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:634) <Info> (SCPrintBuildInfo) -- __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:637) <Info> (SCPrintBuildInfo) -- __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:640) <Info> (SCPrintBuildInfo) -- __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:643) <Info> (SCPrintBuildInfo) -- __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:646) <Info> (SCPrintBuildInfo) -- __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:650) <Info> (SCPrintBuildInfo) -- compiled with -fstack-protector
|
|
|
[2746] 29/8/2012 -- 15:07:25 - (suricata.c:656) <Info> (SCPrintBuildInfo) -- compiled with _FORTIFY_SOURCE=2
|
|
|
|
|
|
During Suricata start up :
|
|
|
...
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
[3071] 29/8/2012 -- 15:23:45 - (detect.c:670) <Info> (SigLoadSignatures) -- Loading rule file: /var/data/peter/md5test.rules
|
|
|
[3071] 29/8/2012 -- 15:23:45 - (detect-filemd5.c:105) <Error> (Md5ReadString) -- [ERRCODE: SC_ERR_INVALID_MD5(214)] - md5 string not 32 bytes
|
|
|
[3071] 29/8/2012 -- 15:24:25 - (detect-filemd5.c:277) <Info> (DetectFileMd5Parse) -- MD5 hash size 1399625840 bytes, negated match
|
|
|
[3071] 29/8/2012 -- 15:24:25 - (detect.c:701) <Info> (SigLoadSignatures) -- 5 rule files processed. 4641 rules succesfully loaded, 0 rules failed
|
|
|
|
|
|
|
|
|
You will get the
|
|
|
|
|
|
::
|
|
|
|
|
|
[ERRCODE: SC_ERR_INVALID_MD5(214)] - md5 string not 32 bytes
|
|
|
|
|
|
if a line of the file is not containing a proper MD5 hash.
|
|
|
|
|
|
For example above we get the err message (which is more of a warning) because in the file , the first line was containing:
|
|
|
"SHA-1","MD5","CRC32","FileName","FileSize","ProductCode","OpSystemCode","SpecialCode"
|
|
|
|
|
|
However , nonetheless Suricata will continue loading the rest of the MD5 hashes from the file. REMEMBER - you would need put only the MD5 hashes in the file.
|
|
|
|
|
|
|
|
|
Then we just created the following test rules:
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
root@suricata:/etc/suricata/peter-yaml# cat /var/data/peter/md5test.rules
|
|
|
alert http any any -> any any (msg:"FILE MD5 Check PDF against a white list"; filemagic:"pdf"; filemd5:!MD5_NSRFile.txt; sid:9966699; rev:1;)
|
|
|
alert http any any -> any any (msg:"FILE MD5 Check EXE against a white list"; filemagic:"exe"; filemd5:!MD5_NSRFile.txt; sid:9977799; rev:2;)
|
|
|
|
|
|
Make sure the **MD5_NSRFile.txt** file (containing the MD5 hashes) is in your "rules directory" (where you load the rules from).
|
|
|
|
|
|
|
|
|
Basically the two rules above are telling Suricata to do the following:
|
|
|
1. If you see a PDF document that has a MD5 hash NOT in the MD5_NSRFile.txt - generate an alert
|
|
|
2. If you see an EXE file that has a MD5 hash NOT in the MD5_NSRFile.txt - generate an alert
|
|
|
|
|
|
all that on the fly, while inspecting traffic.
|
|
|
|
|
|
|
|
|
Then all that is left is to start Suricata:
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
sudo /usr/local/bin/suricata -c /etc/suricata/peter-yaml/suricata-af-packet-mmap.yaml -s /var/data/peter/md5test.rules --af-packet=eth3
|
|
|
|
|
|
and we get the alerts:
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
08/29/2012-15:38:43.165038 [**] [1:9977799:2] FILE MD5 Check EXE against a white list [**] [Classification: (null)] [Priority: 3] {TCP} y.y.y.y:80 -> x.x.x.x:23836
|
|
|
08/29/2012-15:39:32.551950 [**] [1:9977799:2] FILE MD5 Check EXE against a white list [**] [Classification: (null)] [Priority: 3] {TCP} y.y.y.y:2091 -> x.x.x.x:80
|
|
|
|
|
|
|
|
|
|
|
|
That's it.
|
|
|
|
|
|
You can reverse and use the above rules with a "blacklisting" of MD5 hashes, for example:
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
alert http any any -> any any (msg:"FILE MD5 Check PDF against a black list"; filemagic:"pdf"; filemd5:BlackMD5s.txt; sid:9966699; rev:1;)
|
|
|
|
|
|
You can also use the filestore keyword to store the file on disk and do further analysis on the particular file - or blend it in with other :doc:`../rules/file-keywords`.
|
|
|
|
|
|
Peter Manev
|