wiki:KrakenLogDBOpenSSH

OpenSSH Log Analysis using Kraken Log DB

Install Package

kraken@bombom kraken-env> pkg.install kraken-logdb
Resolving {groupId: org.apache.felix, artifactId: org.apache.felix.ipojo, version: 1.4.0}
  -> trying to download from http://download.krakenapps.org/
  -> resolved
  -> installing: org.apache.felix.ipojo 1.4.0

Resolving {groupId: org.jboss.netty, artifactId: netty, version: 3.2.2.Final}
  -> trying to download from http://download.krakenapps.org/
  -> resolved
  -> installing: org.jboss.netty 3.2.2.Final

Resolving {groupId: org.krakenapps, artifactId: kraken-ipojo, version: 1.1.0}
  -> trying to download from http://download.krakenapps.org/
  -> resolved
  -> installing: org.krakenapps.ipojo 1.1.0

Resolving {groupId: org.krakenapps, artifactId: kraken-bnf, version: 1.0.0}
  -> trying to download from http://download.krakenapps.org/
  -> resolved
  -> installing: org.krakenapps.bnf 1.0.0

Resolving {groupId: org.krakenapps, artifactId: kraken-rpc, version: 1.4.0}
  -> trying to download from http://download.krakenapps.org/
  -> resolved
  -> installing: org.krakenapps.rpc 1.4.0

Resolving {groupId: org.krakenapps, artifactId: kraken-msgbus, version: 1.3.0}
  -> trying to download from http://download.krakenapps.org/
  -> resolved
  -> installing: org.krakenapps.msgbus 1.3.0

Resolving {groupId: org.krakenapps, artifactId: kraken-log-api, version: 1.4.0}
  -> trying to download from http://download.krakenapps.org/
  -> resolved
  -> installing: org.krakenapps.log.api 1.4.0

Resolving {groupId: org.krakenapps, artifactId: kraken-logstorage, version: 1.8.1}
  -> trying to download from http://download.krakenapps.org/
  -> resolved
  -> installing: org.krakenapps.logstorage 1.8.1

Resolving {groupId: org.krakenapps, artifactId: kraken-logdb, version: 0.5.0}
  -> trying to download from http://download.krakenapps.org/
  -> resolved
  -> installing: org.krakenapps.logdb 0.5.0

Starting Bundles
  -> [OK] org.apache.felix.ipojo 1.4.0
  -> [OK] org.jboss.netty 3.2.2.Final
  -> [OK] org.krakenapps.ipojo 1.1.0
  -> [OK] org.krakenapps.bnf 1.0.0
  -> [OK] org.krakenapps.rpc 1.4.0
  -> [OK] org.krakenapps.msgbus 1.3.0
  -> [OK] org.krakenapps.log.api 1.4.0
  -> [OK] org.krakenapps.logstorage 1.8.1
  -> [OK] org.krakenapps.logdb 0.5.0

Complete!

Install logfile parser, geoip and logdb geoip extension for tutorial:

kraken@bombom kraken-env> bundle.install org.krakenapps kraken-logfile-parser
Resolving org.krakenapps/kraken-logfile-parser
  -> trying to download from http://download.krakenapps.org/
bundle [10] loaded
kraken@bombom kraken-env> bundle.start 10
bundle 10 started.
kraken@bombom kraken-env> bundle.install org.krakenapps kraken-geoip
Resolving org.krakenapps/kraken-geoip
  -> trying to download from http://download.krakenapps.org/
bundle [11] loaded
kraken@bombom kraken-env> bundle.start 11
bundle 11 started.
kraken@bombom kraken-env> bundle.install org.krakenapps kraken-logdb-geoip
Resolving org.krakenapps/kraken-logdb-geoip
  -> trying to download from http://download.krakenapps.org/
bundle [12] loaded
kraken@bombom kraken-env> bundle.start 12
bundle 12 started.
kraken@bombom kraken-env> geoip.install
downloading geoip city data
unzipping geoip_blocks.bin
unzipping geoip_locs.csv
unzipping geoip_locs.idx
install completed

Step-by-Step Log Auditing

Kraken Log DB can query any textfile. Let's start with /var/log/secure log file (I've copied "secure" log file to my windows machine) Original log lines are printed with some option (offset and limit):

kraken@bombom kraken-env> logdb.query "textfile offset=5 limit=10 secure"
{line=Jan 22 16:10:48 yankees sshd[17793]: pam_unix(sshd:session): session closed for user xeraph}
{line=Jan 22 18:16:50 yankees sshd[27230]: Did not receive identification string from 223.4.120.212}
{line=Jan 22 21:52:47 yankees sshd[11983]: reverse mapping checking getaddrinfo for rev.opentransfer.com.252.251.83.173.in-addr.arpa failed - POSSIBLE BREAK-IN ATTEMPT!}
{line=Jan 22 21:52:47 yankees sshd[11983]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=173.83.251.252  user=root}
{line=Jan 22 21:52:49 yankees sshd[11983]: Failed password for root from 173.83.251.252 port 51549 ssh2}
{line=Jan 22 21:52:49 yankees sshd[11984]: Received disconnect from 173.83.251.252: 11: Bye Bye}
{line=Jan 22 21:52:51 yankees sshd[11987]: reverse mapping checking getaddrinfo for rev.opentransfer.com.252.251.83.173.in-addr.arpa failed - POSSIBLE BREAK-IN ATTEMPT!}
{line=Jan 22 21:52:51 yankees sshd[11987]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=173.83.251.252  user=root}
{line=Jan 22 21:52:53 yankees sshd[11987]: Failed password for root from 173.83.251.252 port 51870 ssh2}
{line=Jan 22 21:52:53 yankees sshd[11988]: Received disconnect from 173.83.251.252: 11: Bye Bye}

We need openssh log parser for detail analysis. Fortunately, we already installed kraken-logfile-parser:

kraken@bombom kraken-env> logapi.parserFactories
Log Parser Factories
----------------------
delimiter
httpd
openssh

Let's parse openssh logs:

kraken@bombom kraken-env> logdb.query "textfile offset=5 limit=10 parser=openssh secure"
{_time=Sun Jan 22 16:10:48 KST 2012, account=xeraph, category=session, host=yankees, logger=sshd[17793], logtype=openssh, result=closed, type=login}
{_time=Sun Jan 22 21:52:47 KST 2012, host=yankees, logger=sshd[11983], logtype=openssh, type=login}
{_time=Sun Jan 22 21:52:49 KST 2012, account=root, host=yankees, logger=sshd[11983], logtype=openssh, protocol=ssh2, result=failure, src_ip=173.83.251.252, src_port=51549, type=login}
{_time=Sun Jan 22 21:52:51 KST 2012, host=yankees, logger=sshd[11987], logtype=openssh, type=login}
{_time=Sun Jan 22 21:52:53 KST 2012, account=root, host=yankees, logger=sshd[11987], logtype=openssh, protocol=ssh2, result=failure, src_ip=173.83.251.252, src_port=51870, type=login}
{_time=Sun Jan 22 21:52:55 KST 2012, host=yankees, logger=sshd[11990], logtype=openssh, type=login}
{_time=Sun Jan 22 21:52:57 KST 2012, account=root, host=yankees, logger=sshd[11990], logtype=openssh, protocol=ssh2, result=failure, src_ip=173.83.251.252, src_port=52155, type=login}
{_time=Sun Jan 22 21:52:59 KST 2012, host=yankees, logger=sshd[11994], logtype=openssh, type=login}
{_time=Sun Jan 22 21:53:01 KST 2012, account=root, host=yankees, logger=sshd[11994], logtype=openssh, protocol=ssh2, result=failure, src_ip=173.83.251.252, src_port=52448, type=login}
{_time=Sun Jan 22 21:53:02 KST 2012, host=yankees, logger=sshd[11999], logtype=openssh, type=login}
0.1s

OK, Let's try to figure out bruteforce attacks. For all failure login attempts (search result == failure), count per source ip address (stats count by src_ip), and sort in descending order (sort -count):

kraken@bombom kraken-env> logdb.query "textfile parser=openssh secure | search result == failure | stats count by src_ip | sort -count"
{count=5239, src_ip=223.4.120.212}
{count=561, src_ip=122.141.244.72}
{count=43, src_ip=173.83.251.252}
{count=30, src_ip=218.203.165.172}
{count=1, src_ip=121.129.106.19}
0.3s

Where do they come from? Let's use geoip extension (added "lookup geoip src_ip output country"):

kraken@bombom kraken-env> logdb.query "textfile parser=openssh secure | search result == failure | stats count by src_ip | sort -count | lookup geoip src_ip output country"
{count=5239, country=null, src_ip=223.4.120.212}
{count=561, country=CN, src_ip=122.141.244.72}
{count=43, country=US, src_ip=173.83.251.252}
{count=30, country=CN, src_ip=218.203.165.172}
{count=1, country=KR, src_ip=121.129.106.19}
0.4s

Let's see overall attack distribution (see count per 10min by source ip address using timechart span=10m count(src_ip) by src_ip):

kraken@bombom kraken-env> logdb.query "textfile parser=openssh secure | search result == failure | timechart span=10m count(src_ip) by src_ip"
{173.83.251.252=43, _time=Sun Jan 22 21:50:00 KST 2012}
{218.203.165.172=15, _time=Sun Jan 22 23:20:00 KST 2012}
{218.203.165.172=15, _time=Mon Jan 23 02:20:00 KST 2012}
{223.4.120.212=86, _time=Mon Jan 23 05:20:00 KST 2012}
{223.4.120.212=217, _time=Mon Jan 23 05:30:00 KST 2012}
{223.4.120.212=222, _time=Mon Jan 23 05:40:00 KST 2012}
{223.4.120.212=220, _time=Mon Jan 23 05:50:00 KST 2012}
{223.4.120.212=219, _time=Mon Jan 23 06:00:00 KST 2012}
{223.4.120.212=215, _time=Mon Jan 23 06:10:00 KST 2012}
{223.4.120.212=223, _time=Mon Jan 23 06:20:00 KST 2012}
{223.4.120.212=218, _time=Mon Jan 23 06:30:00 KST 2012}
{223.4.120.212=218, _time=Mon Jan 23 06:40:00 KST 2012}
{223.4.120.212=218, _time=Mon Jan 23 06:50:00 KST 2012}
{223.4.120.212=214, _time=Mon Jan 23 07:00:00 KST 2012}
{223.4.120.212=220, _time=Mon Jan 23 07:10:00 KST 2012}
{223.4.120.212=215, _time=Mon Jan 23 07:20:00 KST 2012}
{223.4.120.212=217, _time=Mon Jan 23 07:30:00 KST 2012}
{223.4.120.212=219, _time=Mon Jan 23 07:40:00 KST 2012}
{223.4.120.212=218, _time=Mon Jan 23 07:50:00 KST 2012}
{223.4.120.212=223, _time=Mon Jan 23 08:00:00 KST 2012}
{223.4.120.212=216, _time=Mon Jan 23 08:10:00 KST 2012}
{223.4.120.212=221, _time=Mon Jan 23 08:20:00 KST 2012}
{223.4.120.212=218, _time=Mon Jan 23 08:30:00 KST 2012}
{223.4.120.212=222, _time=Mon Jan 23 08:40:00 KST 2012}
{223.4.120.212=217, _time=Mon Jan 23 08:50:00 KST 2012}
{223.4.120.212=219, _time=Mon Jan 23 09:00:00 KST 2012}
{223.4.120.212=222, _time=Mon Jan 23 09:10:00 KST 2012}
{223.4.120.212=122, _time=Mon Jan 23 09:20:00 KST 2012}
{122.141.244.72=5, _time=Tue Jan 24 04:30:00 KST 2012}
{122.141.244.72=214, _time=Tue Jan 24 04:40:00 KST 2012}
{122.141.244.72=215, _time=Tue Jan 24 04:50:00 KST 2012}
{122.141.244.72=127, _time=Tue Jan 24 05:00:00 KST 2012}
{121.129.106.19=1, _time=Tue Jan 24 15:40:00 KST 2012}
0.3s

Let's see 223.4.120.212's attack timeline:

kraken@bombom kraken-env> logdb.query "textfile parser=openssh secure | search src_ip == 223.4.120.212 | timechart span=10m count(src_ip) by src_ip"
{223.4.120.212=86, _time=Mon Jan 23 05:20:00 KST 2012}
{223.4.120.212=217, _time=Mon Jan 23 05:30:00 KST 2012}
{223.4.120.212=222, _time=Mon Jan 23 05:40:00 KST 2012}
{223.4.120.212=220, _time=Mon Jan 23 05:50:00 KST 2012}
{223.4.120.212=219, _time=Mon Jan 23 06:00:00 KST 2012}
{223.4.120.212=215, _time=Mon Jan 23 06:10:00 KST 2012}
{223.4.120.212=223, _time=Mon Jan 23 06:20:00 KST 2012}
{223.4.120.212=218, _time=Mon Jan 23 06:30:00 KST 2012}
{223.4.120.212=218, _time=Mon Jan 23 06:40:00 KST 2012}
{223.4.120.212=218, _time=Mon Jan 23 06:50:00 KST 2012}
{223.4.120.212=214, _time=Mon Jan 23 07:00:00 KST 2012}
{223.4.120.212=220, _time=Mon Jan 23 07:10:00 KST 2012}
{223.4.120.212=215, _time=Mon Jan 23 07:20:00 KST 2012}
{223.4.120.212=217, _time=Mon Jan 23 07:30:00 KST 2012}
{223.4.120.212=219, _time=Mon Jan 23 07:40:00 KST 2012}
{223.4.120.212=218, _time=Mon Jan 23 07:50:00 KST 2012}
{223.4.120.212=223, _time=Mon Jan 23 08:00:00 KST 2012}
{223.4.120.212=216, _time=Mon Jan 23 08:10:00 KST 2012}
{223.4.120.212=221, _time=Mon Jan 23 08:20:00 KST 2012}
{223.4.120.212=218, _time=Mon Jan 23 08:30:00 KST 2012}
{223.4.120.212=222, _time=Mon Jan 23 08:40:00 KST 2012}
{223.4.120.212=217, _time=Mon Jan 23 08:50:00 KST 2012}
{223.4.120.212=219, _time=Mon Jan 23 09:00:00 KST 2012}
{223.4.120.212=222, _time=Mon Jan 23 09:10:00 KST 2012}
{223.4.120.212=122, _time=Mon Jan 23 09:20:00 KST 2012}
0.3s

Show me brute-forced account names:

kraken@bombom kraken-env> logdb.query "textfile parser=openssh secure | search result == failure | stats count by account | sort -count"
{account=root, count=5797}
{account=bin, count=24}
{account=oracle, count=7}
{account=nagios, count=5}
{account=smbuser, count=5}
{account=postgres, count=4}
{account=usuario, count=4}
{account=prueba, count=4}
{account=mysql, count=3}
{account=test, count=2}
{account=util1, count=1}
{account=anthony, count=1}
{account=gnax, count=1}
{account=portal, count=1}
{account=michael, count=1}
{account=paulb, count=1}
{account=radmin, count=1}
{account=admin, count=1}
{account=user0, count=1}
{account=lday, count=1}
{account=mbkim, count=1}
{account=PruncuTz, count=1}
{account=ftpuser, count=1}
{account=jboss, count=1}
{account=zt, count=1}
{account=jhshin, count=1}
{account=nexus, count=1}
{account=connect, count=1}
0.4s

Show me brute-forced account names per attacker ip:

kraken@bombom kraken-env> logdb.query "textfile parser=openssh secure | search result == failure | stats count by src_ip, account | sort -count"
{account=root, count=5239, src_ip=223.4.120.212}
{account=root, count=489, src_ip=122.141.244.72}
{account=root, count=43, src_ip=173.83.251.252}
{account=root, count=26, src_ip=218.203.165.172}
{account=bin, count=24, src_ip=122.141.244.72}
{account=oracle, count=5, src_ip=122.141.244.72}
{account=nagios, count=5, src_ip=122.141.244.72}
{account=smbuser, count=5, src_ip=122.141.244.72}
{account=postgres, count=4, src_ip=122.141.244.72}
{account=usuario, count=4, src_ip=122.141.244.72}
{account=prueba, count=4, src_ip=122.141.244.72}
{account=mysql, count=3, src_ip=122.141.244.72}
{account=oracle, count=2, src_ip=218.203.165.172}
{account=test, count=2, src_ip=218.203.165.172}
{account=connect, count=1, src_ip=122.141.244.72}
{account=gnax, count=1, src_ip=122.141.244.72}
{account=portal, count=1, src_ip=122.141.244.72}
{account=util1, count=1, src_ip=122.141.244.72}
{account=paulb, count=1, src_ip=122.141.244.72}
{account=user0, count=1, src_ip=122.141.244.72}
{account=jboss, count=1, src_ip=122.141.244.72}
{account=zt, count=1, src_ip=122.141.244.72}
{account=PruncuTz, count=1, src_ip=122.141.244.72}
{account=nexus, count=1, src_ip=122.141.244.72}
{account=anthony, count=1, src_ip=122.141.244.72}
{account=jhshin, count=1, src_ip=122.141.244.72}
{account=ftpuser, count=1, src_ip=122.141.244.72}
{account=radmin, count=1, src_ip=122.141.244.72}
{account=lday, count=1, src_ip=122.141.244.72}
{account=admin, count=1, src_ip=122.141.244.72}
{account=michael, count=1, src_ip=122.141.244.72}
{account=mbkim, count=1, src_ip=122.141.244.72}
0.3s