<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://lms.onnocenter.or.id/wiki/index.php?action=history&amp;feed=atom&amp;title=HoneyPot%3A_Dionaea_SQL_Logging</id>
	<title>HoneyPot: Dionaea SQL Logging - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://lms.onnocenter.or.id/wiki/index.php?action=history&amp;feed=atom&amp;title=HoneyPot%3A_Dionaea_SQL_Logging"/>
	<link rel="alternate" type="text/html" href="https://lms.onnocenter.or.id/wiki/index.php?title=HoneyPot:_Dionaea_SQL_Logging&amp;action=history"/>
	<updated>2026-04-20T10:38:10Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://lms.onnocenter.or.id/wiki/index.php?title=HoneyPot:_Dionaea_SQL_Logging&amp;diff=36629&amp;oldid=prev</id>
		<title>Onnowpurbo: New page: logging  Nepenthes had awful logging, huge logfiles, pretty useless for most people. Some people even started writing parsers for the logfiles to extract&amp;convert the usefull information fo...</title>
		<link rel="alternate" type="text/html" href="https://lms.onnocenter.or.id/wiki/index.php?title=HoneyPot:_Dionaea_SQL_Logging&amp;diff=36629&amp;oldid=prev"/>
		<updated>2013-04-13T22:02:11Z</updated>

		<summary type="html">&lt;p&gt;New page: logging  Nepenthes had awful logging, huge logfiles, pretty useless for most people. Some people even started writing parsers for the logfiles to extract&amp;amp;convert the usefull information fo...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;logging&lt;br /&gt;
&lt;br /&gt;
Nepenthes had awful logging, huge logfiles, pretty useless for most people. Some people even started writing parsers for the logfiles to extract&amp;amp;convert the usefull information for use in a database. For dionaea, I decided to stick with awful logging to textfiles, but provide a useful alternative which is easy to setup and maintain, feature rich and allows retrieving information in a useful way, so you don&amp;#039;t have to grep.&lt;br /&gt;
Therefore, SQLite is used to write usefull information down to disk in the logsql.py script.&lt;br /&gt;
I know, SQLite is not PostgreSQL, PostgreSQL is superior in many ways, but it requires some more steps to setup, where SQLite just works out of the box. SQLite does not support concurrency, but as dionaea does not access the database simulaneaously, there were no problems with database-concurrency. On the other hand, if it works with SQLite, it will work with PostgreSQL too, all you&amp;#039;ll have to do is adjust some things.&lt;br /&gt;
&lt;br /&gt;
The definition of useful information is undefined, therefore I decided to go for things I want to see for now:&lt;br /&gt;
&lt;br /&gt;
    connections&lt;br /&gt;
    exploits&lt;br /&gt;
    malware offers&lt;br /&gt;
    malware downloads&lt;br /&gt;
&lt;br /&gt;
SQLite rocks&lt;br /&gt;
&lt;br /&gt;
After adjusting the code, to be able to indicate a relation between connections, I had to recompile dionaea&amp;#039;s python to support sqlite, and updated the docs.&lt;br /&gt;
After verifying &amp;#039;import sqlite3&amp;#039; worked, I started hacking the code to log incidents to the database.&lt;br /&gt;
Once some things got into the database, I wrote some queries to make use of the data.&lt;br /&gt;
attacked ports&lt;br /&gt;
&lt;br /&gt;
Which ports got the most connections incoming:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	COUNT(local_port) AS hitcount, &lt;br /&gt;
	local_port AS port&lt;br /&gt;
FROM &lt;br /&gt;
	connections  &lt;br /&gt;
WHERE &lt;br /&gt;
	connection_type = &amp;#039;accept&amp;#039; &lt;br /&gt;
GROUP BY &lt;br /&gt;
	local_port &lt;br /&gt;
HAVING &lt;br /&gt;
	COUNT(local_port) &amp;gt; 10&lt;br /&gt;
&lt;br /&gt;
hitcount	port&lt;br /&gt;
75	80&lt;br /&gt;
995	135&lt;br /&gt;
3982	445&lt;br /&gt;
29	1957&lt;br /&gt;
attacks over a day&lt;br /&gt;
&lt;br /&gt;
Distribution of the attacks over a day:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	ROUND((connection_timestamp%(3600*24))/3600) AS hour,&lt;br /&gt;
	COUNT(*) &lt;br /&gt;
FROM &lt;br /&gt;
	connections &lt;br /&gt;
WHERE &lt;br /&gt;
	connection_parent IS NULL &lt;br /&gt;
GROUP BY &lt;br /&gt;
	ROUND((connection_timestamp%(3600*24))/3600);&lt;br /&gt;
&lt;br /&gt;
hour	hits&lt;br /&gt;
0.0	20&lt;br /&gt;
1.0	140&lt;br /&gt;
2.0	220&lt;br /&gt;
3.0	352&lt;br /&gt;
4.0	299&lt;br /&gt;
5.0	42&lt;br /&gt;
6.0	200&lt;br /&gt;
12.0	283&lt;br /&gt;
13.0	302&lt;br /&gt;
14.0	227&lt;br /&gt;
15.0	647&lt;br /&gt;
16.0	351&lt;br /&gt;
17.0	264&lt;br /&gt;
18.0	274&lt;br /&gt;
19.0	398&lt;br /&gt;
20.0	285&lt;br /&gt;
21.0	304&lt;br /&gt;
22.0	329&lt;br /&gt;
23.0	142&lt;br /&gt;
24.0	229&lt;br /&gt;
&lt;br /&gt;
As I do not have enough data for a single day yet, we miss the hours 7-11.&lt;br /&gt;
popular malware downloads&lt;br /&gt;
&lt;br /&gt;
Which files got downloaded most:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	COUNT(download_md5_hash), &lt;br /&gt;
	download_md5_hash&lt;br /&gt;
FROM &lt;br /&gt;
	downloads&lt;br /&gt;
GROUP BY&lt;br /&gt;
	download_md5_hash&lt;br /&gt;
ORDER BY&lt;br /&gt;
	COUNT(download_md5_hash) DESC&lt;br /&gt;
&lt;br /&gt;
count(download_md5_hash)	download_md5_hash&lt;br /&gt;
38	df51e3310ef609e908a6b487a28ac068&lt;br /&gt;
19	14a09a48ad23fe0ea5a180bee8cb750a&lt;br /&gt;
6	32b0a00ffb8799a7782a19ee99a0214f&lt;br /&gt;
5	6e0a868563ee18fe6569796c7ce169be&lt;br /&gt;
3	2fa0e36b36382b74e6e6a437ad664a80&lt;br /&gt;
3	329c9d3163d9bf8f4bb9f0d1b846b6aa&lt;br /&gt;
3	4f4f2ebc395b0fbea708acfc3930ec6d&lt;br /&gt;
2	1d419d615dbe5a238bbaa569b3829a23&lt;br /&gt;
1	27f96b0496502104cf0bfc01391e1408&lt;br /&gt;
1	6c9d56535401bbd9052f499d05816ced&lt;br /&gt;
1	a8640b9698542689880b7619dbde1293&lt;br /&gt;
busy attackers&lt;br /&gt;
&lt;br /&gt;
Which host attacked us most:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	COUNT(remote_host),&lt;br /&gt;
	remote_host &lt;br /&gt;
FROM &lt;br /&gt;
	connections &lt;br /&gt;
WHERE &lt;br /&gt;
	connection_type = &amp;#039;accept&amp;#039; &lt;br /&gt;
GROUP BY &lt;br /&gt;
	remote_host &lt;br /&gt;
ORDER BY 	&lt;br /&gt;
	COUNT(remote_host) &lt;br /&gt;
	DESC &lt;br /&gt;
LIMIT &lt;br /&gt;
	10;&lt;br /&gt;
&lt;br /&gt;
COUNT(remote_host)	remote_host&lt;br /&gt;
1655	10.204.202.23&lt;br /&gt;
420	10.2.101.193&lt;br /&gt;
234	10.246.93.128&lt;br /&gt;
224	10.208.119.223&lt;br /&gt;
120	10.54.151.201&lt;br /&gt;
120	10.129.95.105&lt;br /&gt;
120	10.174.16.255&lt;br /&gt;
120	10.234.207.36&lt;br /&gt;
120	10.133.39.52&lt;br /&gt;
120	10.31.104.74&lt;br /&gt;
how often did an attacker ask us to download a file&lt;br /&gt;
&lt;br /&gt;
Count of parent connections remote ip address for each file offerd:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	count(*),&lt;br /&gt;
	download_md5_hash,&lt;br /&gt;
	remote_host &lt;br /&gt;
FROM &lt;br /&gt;
	connections &lt;br /&gt;
NATURAL JOIN &lt;br /&gt;
	downloads &lt;br /&gt;
GROUP BY &lt;br /&gt;
	download_md5_hash,remote_host&lt;br /&gt;
ORDER BY &lt;br /&gt;
	download_md5_hash&lt;br /&gt;
	DESC&lt;br /&gt;
&lt;br /&gt;
count(*)	download_md5_hash	remote_host&lt;br /&gt;
9	df51e3310ef609e908a6b487a28ac068	10.252.215.142&lt;br /&gt;
13	df51e3310ef609e908a6b487a28ac068	10.241.224.0&lt;br /&gt;
1	df51e3310ef609e908a6b487a28ac068	10.224.252.47&lt;br /&gt;
7	df51e3310ef609e908a6b487a28ac068	10.142.138.33&lt;br /&gt;
2	df51e3310ef609e908a6b487a28ac068	10.145.185.98&lt;br /&gt;
1	df51e3310ef609e908a6b487a28ac068	10.18.166.63&lt;br /&gt;
2	df51e3310ef609e908a6b487a28ac068	10.87.54.69&lt;br /&gt;
3	df51e3310ef609e908a6b487a28ac068	10.179.162.134&lt;br /&gt;
1	a8640b9698542689880b7619dbde1293	10.72.12.70&lt;br /&gt;
2	6e0a868563ee18fe6569796c7ce169be	10.92.48.170&lt;br /&gt;
1	6e0a868563ee18fe6569796c7ce169be	10.234.235.205&lt;br /&gt;
1	6e0a868563ee18fe6569796c7ce169be	10.10.88.64&lt;br /&gt;
1	6e0a868563ee18fe6569796c7ce169be	10.1.82.35&lt;br /&gt;
1	6c9d56535401bbd9052f499d05816ced	10.184.18.233&lt;br /&gt;
1	4f4f2ebc395b0fbea708acfc3930ec6d	10.193.184.162&lt;br /&gt;
1	4f4f2ebc395b0fbea708acfc3930ec6d	10.214.246.53&lt;br /&gt;
1	4f4f2ebc395b0fbea708acfc3930ec6d	10.221.108.13&lt;br /&gt;
6	32b0a00ffb8799a7782a19ee99a0214f	10.224.252.47&lt;br /&gt;
1	329c9d3163d9bf8f4bb9f0d1b846b6aa	10.179.215.73&lt;br /&gt;
1	329c9d3163d9bf8f4bb9f0d1b846b6aa	10.141.47.91&lt;br /&gt;
1	329c9d3163d9bf8f4bb9f0d1b846b6aa	10.76.228.187&lt;br /&gt;
3	2fa0e36b36382b74e6e6a437ad664a80	10.197.169.135&lt;br /&gt;
1	27f96b0496502104cf0bfc01391e1408	10.29.109.144&lt;br /&gt;
2	1d419d615dbe5a238bbaa569b3829a23	10.65.34.231&lt;br /&gt;
1	14a09a48ad23fe0ea5a180bee8cb750a	10.65.34.231&lt;br /&gt;
2	14a09a48ad23fe0ea5a180bee8cb750a	10.29.109.144&lt;br /&gt;
4	14a09a48ad23fe0ea5a180bee8cb750a	10.241.224.0&lt;br /&gt;
1	14a09a48ad23fe0ea5a180bee8cb750a	10.224.252.47&lt;br /&gt;
2	14a09a48ad23fe0ea5a180bee8cb750a	10.142.138.33&lt;br /&gt;
3	14a09a48ad23fe0ea5a180bee8cb750a	10.193.67.162&lt;br /&gt;
2	14a09a48ad23fe0ea5a180bee8cb750a	10.145.185.98&lt;br /&gt;
3	14a09a48ad23fe0ea5a180bee8cb750a	10.87.54.69&lt;br /&gt;
1	14a09a48ad23fe0ea5a180bee8cb750a	10.179.162.134&lt;br /&gt;
internal bugfixing&lt;br /&gt;
&lt;br /&gt;
Due to a bug in the logging (I&amp;#039;ll take care, just to prevent complains for early adaptors), the next query required a fix:&lt;br /&gt;
&lt;br /&gt;
UPDATE &lt;br /&gt;
	connections &lt;br /&gt;
SET &lt;br /&gt;
	connection_tree = connection &lt;br /&gt;
WHERE &lt;br /&gt;
	connection_tree IS NULL&lt;br /&gt;
&lt;br /&gt;
distinct attackers per file&lt;br /&gt;
&lt;br /&gt;
Number of distinct attackers per distinct malware file:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	download_md5_hash, &lt;br /&gt;
	COUNT(DISTINCT tree.remote_host) &lt;br /&gt;
FROM &lt;br /&gt;
	downloads &lt;br /&gt;
	NATURAL JOIN connections AS parent &lt;br /&gt;
	JOIN connections AS tree ON (parent.connection == tree.connection_tree) &lt;br /&gt;
GROUP BY &lt;br /&gt;
	download_md5_hash;&lt;br /&gt;
&lt;br /&gt;
download_md5_hash	COUNT(DISTINCT tree.remote_host)&lt;br /&gt;
14a09a48ad23fe0ea5a180bee8cb750a	1&lt;br /&gt;
27f96b0496502104cf0bfc01391e1408	1&lt;br /&gt;
2fa0e36b36382b74e6e6a437ad664a80	1&lt;br /&gt;
329c9d3163d9bf8f4bb9f0d1b846b6aa	3&lt;br /&gt;
32b0a00ffb8799a7782a19ee99a0214f	1&lt;br /&gt;
4f4f2ebc395b0fbea708acfc3930ec6d	3&lt;br /&gt;
6c9d56535401bbd9052f499d05816ced	1&lt;br /&gt;
6e0a868563ee18fe6569796c7ce169be	4&lt;br /&gt;
a8640b9698542689880b7619dbde1293	1&lt;br /&gt;
df51e3310ef609e908a6b487a28ac068	8&lt;br /&gt;
multiple infections/attacking hosts offering different malware files&lt;br /&gt;
&lt;br /&gt;
Now, lets see if we have a host offering more than one malicious file:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	tree.remote_host,&lt;br /&gt;
	COUNT(DISTINCT download_md5_hash) &lt;br /&gt;
FROM &lt;br /&gt;
	downloads &lt;br /&gt;
	NATURAL JOIN connections AS parent &lt;br /&gt;
	JOIN connections AS tree ON (parent.connection == tree.connection_tree) &lt;br /&gt;
GROUP BY &lt;br /&gt;
	tree.remote_host&lt;br /&gt;
HAVING&lt;br /&gt;
	COUNT(DISTINCT download_md5_hash) &amp;gt; 1;&lt;br /&gt;
&lt;br /&gt;
remote_host	COUNT(DISTINCT download_md5_hash)&lt;br /&gt;
10.224.252.47	2&lt;br /&gt;
&lt;br /&gt;
We have one, lets see which files …&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	DISTINCT download_url,&lt;br /&gt;
	offer_url,&lt;br /&gt;
	download_md5_hash&lt;br /&gt;
FROM &lt;br /&gt;
	downloads&lt;br /&gt;
	NATURAL JOIN offers &lt;br /&gt;
	NATURAL JOIN connections AS parent &lt;br /&gt;
	JOIN connections AS tree ON (parent.connection == tree.connection_tree) &lt;br /&gt;
WHERE&lt;br /&gt;
	tree.remote_host = &amp;#039;10.224.252.47&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
download_url	offer_url	download_md5_hash&lt;br /&gt;
fxp://10.224.252.47/ssms.exe 	tfxp://10.224.252.47/ssms.exe 	32b0a00ffb8799a7782a19ee99a0214f&lt;br /&gt;
fxp://10.224.252.47/ssms.exe 	tfxp://10.224.252.47/ssms.exe 	df51e3310ef609e908a6b487a28ac068&lt;br /&gt;
&lt;br /&gt;
Obviously there is a bug, reporting download urls as ftp urls, when they were tftp urls initially … But, the 2 different files come from the same location, so it is likely the tftp transfer broke.&lt;br /&gt;
popular download locations&lt;br /&gt;
&lt;br /&gt;
Number of downloads by location:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	COUNT(*),&lt;br /&gt;
	download_url &lt;br /&gt;
FROM &lt;br /&gt;
	downloads &lt;br /&gt;
GROUP BY &lt;br /&gt;
	download_url &lt;br /&gt;
ORDER BY &lt;br /&gt;
	COUNT(*) &lt;br /&gt;
	DESC;&lt;br /&gt;
&lt;br /&gt;
As mentioned previously, tftp downloads get reported as ftp downloads …&lt;br /&gt;
COUNT(*)	download_url&lt;br /&gt;
13	fxp:://10.241.224.0/ssms.exe&lt;br /&gt;
9	fxp:://10.252.215.142/ssms.exe&lt;br /&gt;
7	fxp:://10.224.252.47/ssms.exe&lt;br /&gt;
7	fxp:://10.142.138.33/ssms.exe&lt;br /&gt;
5	hxxp:://10.181.184.21/i/1i2.zip&lt;br /&gt;
3	fxp:://10.197.169.135/ssms.exe&lt;br /&gt;
3	fxp:://10.179.162.134/ssms.exe&lt;br /&gt;
3	fxp:://1:1@10.241.224.0:64459/ssms.exe&lt;br /&gt;
3	fxp:://1:1@10.87.54.69:42751/ssms.exe&lt;br /&gt;
3	hxxp:://zonetech.info/58.exe&lt;br /&gt;
3	hxxp:://zonetech.info/61.exe&lt;br /&gt;
2	fxp:://10.145.185.98/ssms.exe&lt;br /&gt;
2	fxp:://10.87.54.69/ssms.exe&lt;br /&gt;
2	fxp:://1:1@10.65.34.231:8218/ssms.exe&lt;br /&gt;
2	fxp:://1:1@10.193.67.162:61062/ssms.exe&lt;br /&gt;
1	fxp:://10.65.34.231/ssms.exe&lt;br /&gt;
1	fxp:://10.29.109.144/ssms.exe&lt;br /&gt;
1	fxp:://10.18.166.63/ssms.exe&lt;br /&gt;
1	fxp:://1:1@10.29.109.144:52275/ssms.exe&lt;br /&gt;
1	fxp:://1:1@10.29.109.144:53336/ssms.exe&lt;br /&gt;
1	fxp:://1:1@10.241.224.0:43153/ssms.exe&lt;br /&gt;
1	fxp:://1:1@10.224.252.47:38794/ssms.exe&lt;br /&gt;
1	fxp:://1:1@10.142.138.33:12654/ssms.exe&lt;br /&gt;
1	fxp:://1:1@10.142.138.33:64375/ssms.exe&lt;br /&gt;
1	fxp:://1:1@10.193.67.162:41851/ssms.exe&lt;br /&gt;
1	fxp:://1:1@10.145.185.98:10721/ssms.exe&lt;br /&gt;
1	fxp:://1:1@10.145.185.98:16110/ssms.exe&lt;br /&gt;
1	fxp:://1:1@10.179.162.134:10901/ssms.exe&lt;br /&gt;
1	hxxp:://gutgal.com/sh.php&lt;br /&gt;
1	hxxp:://privcash.cc/r2.exe&lt;br /&gt;
addressed dcerpc calls&lt;br /&gt;
&lt;br /&gt;
Interested which dcerpc calls get attacked most?&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	COUNT(*),&lt;br /&gt;
	dcerpc_uuid,&lt;br /&gt;
	dcerpc_opnum &lt;br /&gt;
FROM &lt;br /&gt;
	dcerpcs &lt;br /&gt;
GROUP BY &lt;br /&gt;
	dcerpc_uuid,&lt;br /&gt;
	dcerpc_opnum &lt;br /&gt;
ORDER BY &lt;br /&gt;
	COUNT(*) &lt;br /&gt;
DESC;&lt;br /&gt;
&lt;br /&gt;
COUNT(*)	dcerpc_uuid	dcerpc_opnum&lt;br /&gt;
1002	12345778-1234-abcd-ef00-0123456789ac	62&lt;br /&gt;
511	3919286a-b10c-11d0-9ba8-00c04fd92ef5	9&lt;br /&gt;
131	000001a0-0000-0000-c000-000000000046	4&lt;br /&gt;
34	4d9f4ab8-7d1c-11cf-861e-0020af6e7c57	0&lt;br /&gt;
30	367abb81-9844-35f1-ad32-98f038001003	27&lt;br /&gt;
21	a0010000-0000-0000-c000-000000000046	4&lt;br /&gt;
12	4b324fc8-1670-01d3-1278-5a47bf6ee188	31&lt;br /&gt;
11	78573412-3412-cdab-ef00-0123456789ac	62&lt;br /&gt;
4	8d9f4e40-a03d-11ce-8f69-08003e30051b	54&lt;br /&gt;
1	6a281939-0cb1-d011-9ba8-00c04fd92ef5	9&lt;br /&gt;
1	c84f324b-7016-d301-1278-5a47bf6ee188	31&lt;br /&gt;
fingerprints&lt;br /&gt;
&lt;br /&gt;
Using p0f, dionaea can collect fingerprints for incoming attacks, lets play with the data …&lt;br /&gt;
operating system genre&lt;br /&gt;
&lt;br /&gt;
Count of operating system genre:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	COUNT(*),&lt;br /&gt;
	p0f_genre &lt;br /&gt;
FROM &lt;br /&gt;
	p0fs &lt;br /&gt;
GROUP BY &lt;br /&gt;
	p0f_genre &lt;br /&gt;
ORDER BY &lt;br /&gt;
	COUNT(*) &lt;br /&gt;
	DESC;&lt;br /&gt;
&lt;br /&gt;
COUNT(*)	p0f_genre&lt;br /&gt;
4491	Windows&lt;br /&gt;
419	&lt;br /&gt;
3	Linux&lt;br /&gt;
&lt;br /&gt;
Windows dominates, 10% unknown …&lt;br /&gt;
operating system&lt;br /&gt;
&lt;br /&gt;
Split by operating system version:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	COUNT(*),&lt;br /&gt;
	p0f_genre,&lt;br /&gt;
	p0f_detail &lt;br /&gt;
FROM &lt;br /&gt;
	p0fs &lt;br /&gt;
GROUP BY &lt;br /&gt;
	p0f_genre,&lt;br /&gt;
	p0f_detail &lt;br /&gt;
ORDER BY &lt;br /&gt;
	COUNT(*) &lt;br /&gt;
	DESC;&lt;br /&gt;
&lt;br /&gt;
COUNT(*)	p0f_genre	p0f_detail&lt;br /&gt;
1539	Windows	XP/2000 (RFC1323+, w+, tstamp-)&lt;br /&gt;
1457	Windows	2000 SP2+, XP SP1+ (seldom 98)&lt;br /&gt;
709	Windows	XP SP1+, 2000 SP3&lt;br /&gt;
615	Windows	2000 SP4, XP SP1+&lt;br /&gt;
419		&lt;br /&gt;
120	Windows	XP/2000 (RFC1323+, w, tstamp-)&lt;br /&gt;
49	Windows	2000 SP4, XP SP1+ (2)&lt;br /&gt;
3	Linux	2.6 (newer, 3)&lt;br /&gt;
2	Windows	2003 (1)&lt;br /&gt;
&lt;br /&gt;
Obviously we are missing Windows Vista and maybe even Windows 7, I&amp;#039;m sure at least Vista got it&amp;#039;s cut on the attacks, but as p0f fingerprints are rather outdated, there is nothing I can do about it. But, once there are more recent fingerprints, identifying Vista and Windows 7, they will show up.&lt;br /&gt;
ports attacked from linux hosts&lt;br /&gt;
&lt;br /&gt;
But, lets see which ports got hit by the Linux hosts:&lt;br /&gt;
&lt;br /&gt;
SELECT &lt;br /&gt;
	COUNT(*),&lt;br /&gt;
	local_port &lt;br /&gt;
FROM &lt;br /&gt;
	connections &lt;br /&gt;
	NATURAL JOIN p0fs &lt;br /&gt;
WHERE &lt;br /&gt;
	p0f_genre = &amp;#039;Linux&amp;#039; &lt;br /&gt;
GROUP BY &lt;br /&gt;
	local_port; &lt;br /&gt;
&lt;br /&gt;
COUNT(*)	local_port&lt;br /&gt;
3	80&lt;br /&gt;
&lt;br /&gt;
So, something was accessing the webserver on port 80.&lt;br /&gt;
attacks are trees&lt;br /&gt;
&lt;br /&gt;
Given the possibility to improve a horrible situation from the beginning, I wanted to be able to correlate a malware download with the initiating connection. Unfortunately there can be more than one connection involved before downloading the malware, as an example take an exploit, which spawns a bindshell, which accepts a connection, which triggers a download via ftp. So, you have at least 3 connections, and all belong to each other hierarchical,&lt;br /&gt;
&lt;br /&gt;
    connection to exploitable service #1&lt;br /&gt;
        bindshell listening #2 (parent #1)&lt;br /&gt;
            bindshell accept #3 (parent #2)&lt;br /&gt;
                malware offer (parent #3)&lt;br /&gt;
                malware download (parent #3)&lt;br /&gt;
&lt;br /&gt;
So, as I wanted to store the information in rdbms, namely SQLite, I knew rdbms do not support hierarchical structures that good, you can store information hierarchical, but querying is hard. For example to get the initiating connection for the malware download in previous example you&amp;#039;d have to walk the parents until there is no parent left. Thats no real problem, if you can access the database with a cursor, but SQLite does not support cursors. Therefore, it sounded reasonable to store the id of the upper-most parent for each connection.&lt;br /&gt;
&lt;br /&gt;
    connection to exploitable service #1&lt;br /&gt;
        bindshell listening #2 (parent #1, tree #1)&lt;br /&gt;
            bindshell accept #3 (parent #2, tree #1)&lt;br /&gt;
                malware offer (parent #3, tree #1)&lt;br /&gt;
                malware download (parent #3, tree #1)&lt;br /&gt;
&lt;br /&gt;
I&amp;#039;ll try to explain how to accomplish this in python.&lt;br /&gt;
&lt;br /&gt;
The first snippet resolves a python dbi cursor result, so you get a list of dicts, and can access the items by name instead of an index. It will break if you have multiple columns with the same name, but as long as you take care of forming your queries well, it works fine.&lt;br /&gt;
&lt;br /&gt;
def resolve_result(resultcursor):&lt;br /&gt;
	names = [resultcursor.description[x][0] for x in range(len(resultcursor.description))]&lt;br /&gt;
	resolvedresult = [ dict(zip(names, i)) for i in resultcursor]&lt;br /&gt;
	return resolvedresult&lt;br /&gt;
&lt;br /&gt;
Next, some formatting to print a connection, depending on type:&lt;br /&gt;
&lt;br /&gt;
def print_connection(c, indent):&lt;br /&gt;
	if c[&amp;#039;connection_type&amp;#039;] == &amp;#039;accept&amp;#039;:&lt;br /&gt;
		print(&amp;quot;%*s connection %i %s %s %s %s:%i &amp;lt;- %s:%i&amp;quot; % ( indent, &amp;quot; &amp;quot;, c[&amp;#039;connection&amp;#039;], c[&amp;#039;connection_protocol&amp;#039;], c[&amp;#039;connection_transport&amp;#039;], c[&amp;#039;connection_type&amp;#039;], c[&amp;#039;local_host&amp;#039;], c[&amp;#039;local_port&amp;#039;], c[&amp;#039;remote_host&amp;#039;], c[&amp;#039;remote_port&amp;#039;]) )&lt;br /&gt;
	elif c[&amp;#039;connection_type&amp;#039;] == &amp;#039;connect&amp;#039;:&lt;br /&gt;
		print(&amp;quot;%*s connection %i %s %s %s %s:%i -&amp;gt; %s/%s:%i&amp;quot; % ( indent, &amp;quot; &amp;quot;, c[&amp;#039;connection&amp;#039;], c[&amp;#039;connection_protocol&amp;#039;], c[&amp;#039;connection_transport&amp;#039;], c[&amp;#039;connection_type&amp;#039;], c[&amp;#039;local_host&amp;#039;], c[&amp;#039;local_port&amp;#039;], c[&amp;#039;remote_hostname&amp;#039;], c[&amp;#039;remote_host&amp;#039;], c[&amp;#039;remote_port&amp;#039;]) )&lt;br /&gt;
	elif c[&amp;#039;connection_type&amp;#039;] == &amp;#039;listen&amp;#039;:&lt;br /&gt;
		print(&amp;quot;%*s connection %i %s %s %s %s:%i&amp;quot; % ( indent, &amp;quot; &amp;quot;, c[&amp;#039;connection&amp;#039;], c[&amp;#039;connection_protocol&amp;#039;], c[&amp;#039;connection_transport&amp;#039;], c[&amp;#039;connection_type&amp;#039;], c[&amp;#039;local_host&amp;#039;], c[&amp;#039;local_port&amp;#039;]) )&lt;br /&gt;
&lt;br /&gt;
Now, we open the database and retrieve the root-connections. Root-connections initiate an attack, so they have no parent-connection.&lt;br /&gt;
&lt;br /&gt;
dbh = sqlite3.connect(&amp;quot;/tmp/test.sqlite&amp;quot;)&lt;br /&gt;
cursor = dbh.cursor()&lt;br /&gt;
 &lt;br /&gt;
result = cursor.execute(&amp;quot;SELECT * from connections WHERE connection_tree = connection OR connection_tree IS NULL &amp;quot;)&lt;br /&gt;
connections = resolve_result(result)&lt;br /&gt;
&lt;br /&gt;
Now we can iterate through the connections, and print each connections information:&lt;br /&gt;
&lt;br /&gt;
for c in connections:&lt;br /&gt;
	connection = c[&amp;#039;connection&amp;#039;]&lt;br /&gt;
	print_connection(c, 1)&lt;br /&gt;
&lt;br /&gt;
But we want to print the child-connections too, and the possible child-child-connection, and possible child-child-child …, so we will use recursion:&lt;br /&gt;
&lt;br /&gt;
def recursive_print(cursor, connection, indent):&lt;br /&gt;
	result = cursor.execute(&amp;quot;SELECT * from connections WHERE connection_parent = ?&amp;quot;, (connection, ))&lt;br /&gt;
	connections = resolve_result(result)&lt;br /&gt;
	for c in connections:&lt;br /&gt;
		if c[&amp;#039;connection&amp;#039;] == connection:&lt;br /&gt;
			continue&lt;br /&gt;
		print_connection(c, indent)&lt;br /&gt;
		recursive_print(cursor, c[&amp;#039;connection&amp;#039;], indent+2)&lt;br /&gt;
&lt;br /&gt;
and change the loop on all root connections to print the child-connections too:&lt;br /&gt;
&lt;br /&gt;
for c in connections:&lt;br /&gt;
	connection = c[&amp;#039;connection&amp;#039;]&lt;br /&gt;
	print_connection(c, 1)&lt;br /&gt;
	recursive_print(cursor, c[&amp;#039;connection&amp;#039;], 2)&lt;br /&gt;
&lt;br /&gt;
This already gives good results:&lt;br /&gt;
&lt;br /&gt;
  connection 610 smbd tcp accept 10.69.53.52:445 &amp;lt;- 10.65.34.231:2010&lt;br /&gt;
   connection 611 remoteshell tcp listen 10.69.53.52:1957&lt;br /&gt;
     connection 612 remoteshell tcp accept 10.69.53.52:1957 &amp;lt;- 10.65.34.231:2135&lt;br /&gt;
       connection 613 ftpctrl tcp connect 10.69.53.52:37065 -&amp;gt; 10.65.34.231/None:8218&lt;br /&gt;
         connection 614 ftpdata tcp listen 10.69.53.52:62087&lt;br /&gt;
           connection 615 ftpdata tcp accept 10.69.53.52:62087 &amp;lt;- 10.65.34.231:2308&lt;br /&gt;
&lt;br /&gt;
After adding code to print all information we have for each connection, it looks like this:&lt;br /&gt;
&lt;br /&gt;
  connection 610 smbd tcp accept 10.69.53.52:445 &amp;lt;- 10.65.34.231:2010&lt;br /&gt;
   dcerpc request: uuid &amp;#039;3919286a-b10c-11d0-9ba8-00c04fd92ef5&amp;#039; opnum 9&lt;br /&gt;
   p0f: genre:&amp;#039;Windows&amp;#039; detail:&amp;#039;XP SP1+, 2000 SP3&amp;#039; uptime:&amp;#039;-1&amp;#039; tos:&amp;#039;&amp;#039; dist:&amp;#039;11&amp;#039; nat:&amp;#039;0&amp;#039; fw:&amp;#039;0&amp;#039;&lt;br /&gt;
   profile: [{&amp;#039;return&amp;#039;: &amp;#039;0x7c802367&amp;#039;, &amp;#039;args&amp;#039;: [&amp;#039;&amp;#039;, &amp;#039;CreateProcessA&amp;#039;], &amp;#039;call&amp;#039;: &amp;#039;GetProcAddress&amp;#039;}, ...., {&amp;#039;return&amp;#039;: &amp;#039;0&amp;#039;, &amp;#039;args&amp;#039;: [&amp;#039;0&amp;#039;], &amp;#039;call&amp;#039;: &amp;#039;ExitThread&amp;#039;}]&lt;br /&gt;
   service: bindshell://1957&lt;br /&gt;
   connection 611 remoteshell tcp listen 10.69.53.52:1957&lt;br /&gt;
     connection 612 remoteshell tcp accept 10.69.53.52:1957 &amp;lt;- 10.65.34.231:2135&lt;br /&gt;
       p0f: genre:&amp;#039;Windows&amp;#039; detail:&amp;#039;XP SP1+, 2000 SP3&amp;#039; uptime:&amp;#039;-1&amp;#039; tos:&amp;#039;&amp;#039; dist:&amp;#039;11&amp;#039; nat:&amp;#039;0&amp;#039; fw:&amp;#039;0&amp;#039;&lt;br /&gt;
       offer: fxp://1:1@10.65.34.231:8218/ssms.exe&lt;br /&gt;
       download: 1d419d615dbe5a238bbaa569b3829a23 fxp://1:1@10.65.34.231:8218/ssms.exe&lt;br /&gt;
       connection 613 ftpctrl tcp connect 10.69.53.52:37065 -&amp;gt; 10.65.34.231/None:8218&lt;br /&gt;
         connection 614 ftpdata tcp listen 10.69.53.52:62087&lt;br /&gt;
           connection 615 ftpdata tcp accept 10.69.53.52:62087 &amp;lt;- 10.65.34.231:2308&lt;br /&gt;
             p0f: genre:&amp;#039;Windows&amp;#039; detail:&amp;#039;XP SP1+, 2000 SP3&amp;#039; uptime:&amp;#039;-1&amp;#039; tos:&amp;#039;&amp;#039; dist:&amp;#039;11&amp;#039; nat:&amp;#039;0&amp;#039; fw:&amp;#039;0&amp;#039;&lt;br /&gt;
&lt;br /&gt;
So, if you want to have a gui for the honeypot, you could use the internal http service and script the webinterface in python, within the honeypot itself, or create static html pages using a cron job and serve them, or push them somewhere else. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Referensi==&lt;br /&gt;
&lt;br /&gt;
* http://carnivore.it/2009/11/06/dionaea_sql_logging&lt;/div&gt;</summary>
		<author><name>Onnowpurbo</name></author>
	</entry>
</feed>