Analysis of DDoS Service Database used to attack Brian Kreb's Website

Last month Brian Krebs' website was subjected to a DDoS attack which Brian covered in two posts:
http://krebsonsecurity.com/2013/03/the-world-has-no-room-for-cowards/
http://krebsonsecurity.com/2013/03/the-obscurest-epoch-is-today/

Brian was also the target of a "Swatting" where his local police force were tricked into responding to a fake / spoofed call from Brian's mobile phone. I'd never heard of swatting until I read his story.

In Brian's efforts to identify the source / perpetrator of the DDoS attack he obtained information that indicated the attacks used a service provided through a site called booter.tw to instigate the DDoS attacks. It seems a dump from their customer database was publicly accessible on their site, which Brian published on his blog. If your interested in understanding what a booter service / site is you can read more about them on Brian's blog here.

While the contents of the database has been analysed by others including Arbor Networks and security researcher, I've included my own analysis (which does somewhat overlap with theirs).

After loading the dump into a MySQL database querying the database shows that the user with the id 126 executed DDoS attacks via the booter.tw site.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
mysql> SELECT ip,owner FROM attacks WHERE ip like '%krebsonsecurity.com%' OR ip = '72.52.7.144';
+--------------------------------+-------+
| ip                             | owner |
+--------------------------------+-------+
| 72.52.7.144                    |   126 |
| 72.52.7.144                    |   126 |
| http://www.krebsonsecurity.com |   126 |
| 72.52.7.144                    |   126 |
| 72.52.7.144                    |   126 |
| http://krebsonsecurity.com     |   126 |
| http://krebsonsecurity.com     |   126 |
| http://krebsonsecurity.com     |   126 |
| http://krebsonsecurity.com/    |   126 |
| http://krebsonsecurity.com/    |   126 |
| http://krebsonsecurity.com/    |   126 |
| http://krebsonsecurity.com/    |   126 |
| http://krebsonsecurity.com/    |   126 |
| http://krebsonsecurity.com     |   126 |
| http://krebsonsecurity.com/    |   126 |
| http://www.krebsonsecurity.com |   126 |
| http://krebsonsecurity.com/    |   126 |
| http://krebsonsecurity.com/    |   126 |
| http://krebsonsecurity.com/    |   126 |
+--------------------------------+-------+
19 rows in set (0.64 sec)

Among other columns / fields the attacks table also records the time the attacks were ordered (or perhaps initiated - it's unclear from the table alone) in the time column - which provides an indication of when the DDoS attack may have started.


1
2
3
4
5
6
mysql> SELECT FROM_UNIXTIME(min(a.time)),FROM_UNIXTIME(max(a.time)) FROM attacks a WHERE a.ip LIKE '%krebs%' OR ip = '72.52.7.144';
+----------------------------+----------------------------+
| FROM_UNIXTIME(min(a.time)) | FROM_UNIXTIME(max(a.time)) |
+----------------------------+----------------------------+
| 2013-03-14 17:02:45        | 2013-03-14 22:36:09        |
+----------------------------+----------------------------+


The sql dump file was dumped on March 15th using phyMyAdmin:

-- phpMyAdmin SQL Dump
-- version 3.5.2
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Mar 15, 2013 at 07:46 AM


The attacks table also records the type of DDoS attack used:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
mysql> SELECT a.type, COUNT(*) FROM attacks a WHERE a.ip LIKE '%krebs%' OR ip = '72.52.7.144' GROUP BY a.type;
+-----------+----------+
| type      | COUNT(*) |
+-----------+----------+
| ARME      |        3 |
| ESSYN     |        3 |
| HTTPGET   |        4 |
| HTTPHEAD  |        1 |
| RUDY      |        6 |
| SLOWLORIS |        1 |
| UDP       |        1 |
+-----------+----------+


So who is the user with the id 126?


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> SELECT * FROM users WHERE id = '126' \G
*************************** 1. row ***************************
                    id: 126
                idhash: 069059b7ef840f0c74a814ec9237b6ec
              username: countonme
              password: e8dc6863dfd3872801be5f3798fbb64eeff86c56fc21f5bde8abd01c24b2b132
                  rank: 1
                  time: 1374469200
         max_boot_time: 7200
max_concurrent_attacks: 3
            lastattack: 72.196.218.2
        ipgrabberimage: http://i.imgur.com/flenQrv.jpg
                banned: false
                lastip: 126.11.70.151
                 email: countonme@gmail.com
                   tos: 1
           sessioncode: zjj8o8bb
            lastactive: 1363305665
           recovercode:
    has_private_server: 0
1 row in set (0.00 sec)


As you may have noticed the password field looks like a SHA256 hash of the password and guess what the passwords are not salted! In other words it's fairly trivial to crack them using standard penetration testing tools such as hashcat if the password is based on a dictionary word.

Countonme's account was created on Jan 25th:


1
2
3
4
5
6
mysql> SELECT id,action,user,FROM_UNIXTIME(time) FROM adminlogs WHERE action LIKE '%count%';
+-----+-----------------------------------------+------+---------------------+
| id  | action                                  | user | FROM_UNIXTIME(time) |
+-----+-----------------------------------------+------+---------------------+
| 119 | Added new user with username: countonme |    1 | 2013-01-25 21:06:23 |
+-----+-----------------------------------------+------+---------------------+

The database also has a logins table which has a record of the time, IP address and user-agent string of the browser used to login to the site.

The SQL query SELECT DISTINCT ip FROM logins WHERE owner = '126'; shows that countonme logged in from 208 different IP addresses.

Since it was unlikely that countonme would be logging in directly from his own computer, I obtained a list of the Tor exit nodes from the Tor website, loaded these into a table and then checked how many of the IPs countonme logged in from were Tor exit nodes.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> create table torexitnodes ( ip text);
Query OK, 0 rows affected (0.03 sec)

mysql> LOAD DATA LOCAL INFILE 'torlist.txt'
    -> INTO TABLE torexitnodes
    -> (ip);
Query OK, 3275 rows affected (0.31 sec)
Records: 3275  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT DISTINCT logins.ip FROM logins,torexitnodes WHERE logins.owner = '126' AND logins.ip = torexitnodes.ip;
+-----------------+
| ip              |
+-----------------+
| 96.44.189.102   |
| 37.130.227.133  |
| 96.47.226.19    |
<removed for brevity>
| 87.236.194.97   |
| 192.81.249.23   |
+-----------------+
53 rows in set (2.06 sec)

Now lets use Maxmind GeoIP database to get a *rough* idea of locations of IPs that are not Tor exit nodes.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
CREATE TABLE blocks (
  startIpNum int(10) unsigned NOT NULL,
  endIpNum int(10) unsigned NOT NULL,
  locId int(10) unsigned NOT NULL,
  PRIMARY KEY (endIpNum)
 );
    
CREATE TABLE location(
  locId int(10) unsigned NOT NULL,
  country char(2) NOT NULL,
  region char(2) NOT NULL,
  city varchar(50),
  postalCode char(5) NOT NULL,
  latitude float,
  longitude float,
  dmaCode integer,
  areaCode integer,
  PRIMARY KEY (locId)
 );
    
    
LOAD DATA LOCAL INFILE 'GeoLiteCity-Blocks.csv'
  INTO TABLE blocks
  FIELDS TERMINATED BY ','
  OPTIONALLY ENCLOSED BY '\"'
  LINES TERMINATED BY '\n';
LOAD DATA LOCAL INFILE 'GeoLiteCity-Location.csv'
  INTO TABLE location
  FIELDS TERMINATED BY ','
  OPTIONALLY ENCLOSED BY '\"'
  LINES TERMINATED BY '\n';

mysql> ALTER TABLE blocks ADD INDEX (startIpNum,endIpNum);
Query OK, 0 rows affected (1 min 1.53 sec)
Records: 0  Duplicates: 0  Warnings: 0


A LEFT JOIN with the torexitnodes table should return those IPs used by countonme that are not Tor exit nodes:

1
2
3
4
mysql> SELECT L.ip
    -> FROM logins L LEFT JOIN torexitnodes T ON L.ip = T.ip
    -> WHERE L.owner = '126' AND T.ip IS NULL
    -> GROUP BY L.ip

This query returns 155 records. After creating a separate table to hold these IPs; created using the query:


1
2
3
4
INSERT INTO com_login_ips_extor(ip)
    SELECT L.ip
    FROM logins L LEFT JOIN torexitnodes T ON L.ip = T.ip
    WHERE L.owner = '126' AND T.ip IS NULL GROUP BY L.ip

- we can then use the Maxmind data to determine approximate locations:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
mysql> SELECT com_login_ips_extor.ip,l.country,l.region,l.city
    ->     FROM com_login_ips_extor,location l JOIN blocks b ON (l.locId=b.locId)
    ->     WHERE( INET_ATON(com_login_ips_extor.ip) >= b.startIpNum AND INET_ATON(com_login_ips_extor.ip) <= b.endIpNum
);
+-----------------+---------+--------+------------------+
| ip              | country | region | city             |
+-----------------+---------+--------+------------------+
| 100.1.99.182    | US      | NJ     | Lodi             |
| 100.42.242.209  | CA      | NS     | Halifax          |
| 108.174.195.211 | US      | OK     | Tulsa            |
<=================REMOVED FOR BREVITY===================>
| 99.110.32.168   | US      | IL     | Schiller Park    |
| 99.59.106.39    | US      | OH     | Mentor           |
+-----------------+---------+--------+------------------+
155 rows in set (11 min 14.50 sec)

Export the list of (non-Tor exit node) IPs to  text file:

mysql> select ip from com_login_ips_extor INTO OUTFILE 'comips.txt';
Query OK, 208 rows affected (0.02 sec)

Edit the file and add "begin origin" as the first line and "end" as the last line in the file

Then use netcat to determine ASN information using ShadowServer:
$ nc asn.shadowserver.org 43 < comips.txt > COM_ASNs.txt

After converting the file into comma-delimited, with values enclosed in double-quotes CSV file, we can import the data into a table in MySQL:



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> describe com_ip_asn_map;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| ip     | text        | YES  |     | NULL    |       |
| asn    | varchar(30) | YES  |     | NULL    |       |
| prefix | text        | YES  |     | NULL    |       |
| asname | text        | YES  |     | NULL    |       |
| cn     | varchar(5)  | YES  |     | NULL    |       |
| domain | varchar(30) | YES  |     | NULL    |       |
| isp    | varchar(30) | YES  |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+
7 rows in set (0.08 sec)

mysql> LOAD DATA LOCAL INFILE 'COM_ASNs_CSVFile.csv'
    ->  INTO TABLE com_ip_asn_map
    ->  FIELDS TERMINATED BY ','
    ->  OPTIONALLY ENCLOSED BY '\"'
    ->  LINES TERMINATED BY '\n';
Query OK, 155 rows affected, 34 warnings (0.05 sec)
Records: 155  Deleted: 0  Skipped: 0  Warnings: 34

We can then obtain an overview of the ISPs that the IPs belong to:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
mysql> SELECT domain,asname, COUNT(ip)
    ->          FROM com_ip_asn_map
    ->          GROUP BY domain
    ->          HAVING COUNT(ip) > 4
    ->          ORDER BY COUNT(ip) DESC;
+---------------+----------------------+-----------+
| domain        | asname               | COUNT(ip) |
+---------------+----------------------+-----------+
|  RR.COM       |  SCRR-10796          |        14 |
|  ATT.NET      |  ATT-INTERNET4       |         9 |
|  VERIZON.COM  |  VZGNI-TRANSIT       |         8 |
|  PLUS.NET     |  PLUSNET             |         8 |
|  COMCAST.NET  |  CCCH-3              |         7 |
|  OVH.COM      |  OVH                 |         5 |
|  CHARTER.NET  |  CHARTER-NET-HKY-NC  |         5 |
|  OPTIMUM.NET  |  CABLE-NET-1         |         5 |
+---------------+----------------------+-----------+


The lastip field of the users table appears to maintain a record of the IP address from which each user last logged in. Let's use this to determine the last IP that countonme logged in from:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> SELECT id,username,lastip FROM users WHERE username = "countonme";
+-----+-----------+---------------+
| id  | username  | lastip        |
+-----+-----------+---------------+
| 126 | countonme | 126.11.70.151 |
+-----+-----------+---------------+
1 row in set (0.03 sec)

mysql> SELECT id,username,lastip,l.country,l.region,l.city
    ->     FROM users, location l JOIN blocks b ON (l.locId=b.locId)
    ->     WHERE username = "countonme"
    ->     AND( INET_ATON(users.lastip) >= b.startIpNum AND INET_ATON(users.lastip) <= b.endIpNum );
+-----+-----------+---------------+---------+--------+------+
| id  | username  | lastip        | country | region | city |
+-----+-----------+---------------+---------+--------+------+
| 126 | countonme | 126.11.70.151 | JP      |        |      |
+-----+-----------+---------------+---------+--------+------+
1 row in set (2.17 sec)

$ whois -h asn.shadowserver.org 'origin 126.11.70.151'
17676 | 126.11.0.0/16 | GIGAINFRA | JP | SOFTBANKBB.CO.JP | JAPAN NATION-WIDE NETWORK OF SOFTBANK BB CORP.

SoftBank Corp. is a Japanese telecommunications and Internet corporation

You can obtain a list of all IP addresses / domains attacked using the query:


1
2
mysql> SELECT DISTINCT(ip) FROM attacks ORDER BY ip INTO OUTFILE 'all_attacked_ips_unique_sorted.txt';
Query OK, 12439 rows affected (4.13 sec)

The IP field contains both IP addresses and domain names as well as URLs, so it would require some processing of the data in order to obtain a view of location of the IPs that were attacked using booter.tw.

Out of interest I ran a query to see how many .gov domains were attacked:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
mysql> SELECT ip, COUNT(ip) FROM attacks GROUP BY ip  HAVING COUNT(ip) >= 1 AND ip like '%.gov%' ORDER BY COUNT(ip);
+---------------------------------------+-----------+
| ip                                    | COUNT(ip) |
+---------------------------------------+-----------+
| http://USA.gov                        |         1 |
| http://aberdeenshire.gov.uk           |         1 |
| http://rashtrapatisachivalaya.gov.in/ |         1 |
| rashtrapatisachivalaya.gov.in/        |         1 |
| http://indianrail.gov.in              |         1 |
| http://speakerloksabha.gov.in         |         1 |
| http://nyc.gov                        |         1 |
| http://police.gov.il                  |         2 |
| http://presidentofindia.gov.in        |         4 |
| http://rashtrapatisachivalaya.gov.in  |        68 |
| http://india.gov.in                   |        86 |
+---------------------------------------+-----------+
11 rows in set (6.61 sec)

Most of these seem to be focused on Indian .gov domains. Looking at the owner field/column most of the attacks on Indian .gov appear to have been ordered by two users Snizzard and Spicycheetah (well actually I believe they are probably the same person).





Comments

Popular Posts