Parsing SSH logs - Intermediate
This is part two of four in a series of articles about security.
- Text Processing Tools in UNIX
- Parsing SSH Logs
- Basics
- Intermediate
- Configuring fail2ban
- Configuring mail (and Slack) for SSH Notifications
This time, I will explore how many times SSH daemon’s own defenses
stopped login attempts and use geoiplookup
to lookup physical
location data on IP addresses found in the log.
SSH daemon’s Defense
SSH itself is not completely defenseless against multiple login attempts in a short period of time. The SSH daemon will start to reject login attempts if the same IP address has multiple consecutive failures.
Total Rejections
From the log, the total number of times SSH disconnected a client because of too many failed attempts:
$ cat megaauth.log | grep -oE 'maximum authentication attempts.*' | wc -l`
SSH log shows there were 895 instances of too many failed attempts. This might not seem like a lot, but these are only the number of times the SSH daemon saw there was more than six failed attempts in a row.
Total Rejections for ‘root’
Number of Maximum Authentication attempts using ‘root’ as the username:
cat megaauth.log | grep -oE 'maximum authentication attempts.*for root' | wc -l
SSH rejected ‘root’ login 614 times in 24 days. This is a very good reason to disable root login on any openly accessible server. ‘root’ is the default administrative username for any UNIX system.
Total Rejections for other names
Number of Maximum Authentication attempts using name other than ‘root’:
cat megaauth.log | grep -oE 'maximum authentication attempts.*for invalid.*' | wc -l
278 login attempts were made using a username other than ‘root’. The most frequently used non-‘root’ username:
cat megaauth.log | grep -oE 'maximum authentication attempts.*for invalid.*' | awk '{ print $8 }' | sort | uniq -c | sort -n
# of attempts | username |
---|---|
3 | administrator |
3 | pi |
4 | mother |
4 | support |
6 | admin1 |
6 | user |
6 | usuario |
16 | ubnt |
17 | test |
169 | admin |
There is some overlap with the most frequently used login name, but it is not as frequent, due to SSH only counting these after the maximum number of attempts have been made.
Using geoiplookup
to map Location
Let’s start with the most frequently seen IP address in the logs:
cat megaauth.log | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | sort | uniq -c | sort -n | tail
occurences | address |
---|---|
634 | 182.61.21.189 |
696 | 88.150.230.127 |
732 | 121.42.48.1 |
972 | 113.5.255.22 |
1029 | 151.12.60.131 |
1128 | 107.155.6.41 |
1169 | 121.248.150.13 |
1704 | 61.183.15.243 |
2635 | 81.212.109.229 |
17869 | 155.133.16.246 |
Countries where these IP address are located:
cat megaauth.log | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | awk '{ system("geoiplookup " $1) }' | awk '{ $1="";$2="";$3=""; print $0 }' | sort | uniq -c | sort -n | tail
Country | Occurrence |
---|---|
KR, Korea, Republic of | 591 |
FR, France | 607 |
RU, Russian Federation | 665 |
GB, United Kingdom | 730 |
IT, Italy | 1223 |
NL, Netherlands | 1579 |
US, United States | 2424 |
TR, Turkey | 3130 |
CN, China | 10190 |
PL, Poland | 17912 |
For the next section, to improve processing, creating an intermediate file, country_ip.log that maps IP address with its associated country.
cat auth.log | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | awk '{ print $0 system("geoiplookup " $1) }' | tr '\n' '|' | xargs -n 2 -d '|' | sed -n -e 's/0$//p' | sed -n -e 's/GeoIP Country Edition: //p' | awk '{ printf("%s %s\n", $(NF), $0 ) } END { print }' | awk '{ $(NF)=""; print $0 }' | head -n -1 > country_ip.log
note: this is pretty messy, so if there’s a better way to get this done, let me know!
How many Different Countries?
cat country_ip.log | awk '{ $1=""; print $0 }' | sort | uniq | wc -l
There were a total of 67 difference countries that showed up in the SSH log. There are 193 UN countries in the world. So, almost 33% of known countries in the world accessed this server in a period of 24 days.
Let’s take a look at how many times each country accessed the server, how many different IPs from the country, average, minimum, and maximum number of access.
country | number of occurences | unique IPs | average occurences | min | max |
---|---|---|---|---|---|
FR, France | 267 | 28 | 9 | 1 | 2 |
SE, Sweden | 308 | 3 | 102 | 2 | 300 |
MY, Malaysia | 313 | 2 | 156 | 13 | 300 |
JP, Japan | 334 | 12 | 27 | 1 | 300 |
RU, Russian Federation | 490 | 96 | 5 | 1 | 213 |
NL, Netherlands | 1056 | 12 | 88 | 1 | 480 |
IT, Italy | 1158 | 14 | 82 | 1 | 1029 |
US, United States | 1588 | 85 | 18 | 1 | 692 |
CN, China | 7228 | 299 | 24 | 1 | 1704 |
PL, Poland | 17908 | 7 | 2558 | 1 | 17868 |
How items were calculated:
- number of occurences:
cat country_ip.log | awk '{ $1=""; print $0 }' | sort | uniq -c | sort -n | tail
- unique IPs:
cat country_ip.log | grep 'PL' | sort | uniq | wc -l
- average : num occureneces / uniq IPs
- min:
cat country_ip.log | grep '<country code>' | sort | uniq -c | sort -n | head -n 1
- max:
cat country_ip.log | grep '<country code>' | sort | uniq -c | sort -n | tail -n 1
Poland really stood out, not only with the number of occurences, but basically a single individual showed up in the SSH log more than 17,000 times!
Port Scans per Country
The number of port scans performed by country can be obtained using this command:
cat megaauth.log | grep -oE 'Received disconnect.*' | awk '{ print $4 }' | sed -n -e 's/://p' | awk '{ print $0 system("geoiplookup " $1) }' | tr '\n' '|' | xargs -n 2 -d '|' | sed -n -e 's/0$//p' | sed -n -e 's/GeoIP Country Edition: //p' | awk '{ printf("%s %s\n", $(NF), $0 ) } END { print }' | awk '{ $(NF)=""; print $0 }' | head -n -1 | awk '{ $1=""; print $0 }' | sort | uniq -c | sort -n | tail
Country | Port scans |
---|---|
VN, Vietnam | 140 |
RU, Russian Federation | 228 |
GB, United Kingdom | 379 |
NL, Netherlands | 439 |
KR, Korea, Republic of | 518 |
IT, Italy | 609 |
TR, Turkey | 743 |
US, United States | 762 |
PL, Poland | 4686 |
CN, China | 5627 |
Interesting, China & Poland based IP addresses seemed to have done the most port scans.
Attempted logins per Country
cat megaauth.log | grep -oE 'Invalid user.*' | awk '{ print $5 }' | awk '{ print $0 system("geoiplookup " $1) }' | tr '\n' '|' | xargs -n 2 -d '|' | sed -n -e 's/0$//p' | sed -n -e 's/GeoIP Country Edition: //p' | awk '{ printf("%s %s\n", $(NF), $0 ) } END { print }' | awk '{ $(NF)=""; print $0 }' | head -n -1 | awk '{ $1=""; print $0 }' | sort | uniq -c | sort -n | tail
Country | Attempted logins |
---|---|
PA, Panama | 106 |
RU, Russian Federation | 117 |
FR, France | 135 |
VN, Vietnam | 147 |
NL, Netherlands | 230 |
CN, China | 251 |
GB, United Kingdom | 325 |
US, United States | 444 |
IT, Italy | 494 |
TR, Turkey | 618 |
The number of attempted logins was not really dominated by any one country like port scans.
ubnt???
From
part 1
of this, I encountered many login attempts with the username:
ubnt
. How many countries tried to login with ubnt
username?
cat megaauth.log | grep -oE 'Invalid user ubnt.*' | awk '{ print $5 }' | awk '{ print $0 system("geoiplookup " $1) }' | tr '\n' '|' | xargs -n 2 -d '|' | sed -n -e 's/0$//p' | sed -n -e 's/GeoIP Country Edition: //p' | awk '{ printf("%s %s\n", $(NF), $0 ) } END { print }' | awk '{ $(NF)=""; print $0 }' | head -n -1 | awk '{ $1=""; print $0 }' | sort | uniq | wc -l
A total of 19 different countries used ubnt
to login.
How about which countries attempted the most?
cat megaauth.log | grep -oE 'Invalid user ubnt.*' | awk '{ print $5 }' | awk '{ print $0 system("geoiplookup " $1) }' | tr '\n' '|' | xargs -n 2 -d '|' | sed -n -e 's/0$//p' | sed -n -e 's/GeoIP Country Edition: //p' | awk '{ printf("%s %s\n", $(NF), $0 ) } END { print }' | awk '{ $(NF)=""; print $0 }' | head -n -1 | awk '{ $1=""; print $0 }' | sort | uniq -c | sort -n | tail
Country | Number of ‘ubnt’ attempts |
---|---|
TW, Taiwan | 1 |
UA, Ukraine | 1 |
CA, Canada | 2 |
AR, Argentina | 3 |
BR, Brazil | 3 |
US, United States | 4 |
FR, France | 11 |
NL, Netherlands | 27 |
RU, Russian Federation | 34 |
CN, China | 330 |
Most are non-English speaking countries, but even Canada and the United States are on this list.
City level
The interesting thing about geoiplookup
, is that there is an option of using the city database to get finer
- most seen IP in log in general (city)
cat auth.log | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | awk '{ system("geoiplookup -f /usr/share/GeoIP/GeoLiteCity.dat " $1) }' | awk '{ $1="";$2="";$3="";$4="";$5=""; print $0 }' | sort | uniq -c | sort -n | tail
City level data | Occurences |
---|---|
IT, 07, Lazio, Rome, 00141, 41.891899, 12.511300, 0, 0 | 1029 |
CN, 08, Heilongjiang, Harbin, N/A, 45.750000, 126.650002, 0, 0 | 1043 |
US, CA, California, Los Angeles, 90017, 34.058399, -118.278000, 803, 213 | 1129 |
CN, 02, Zhejiang, Hangzhou, N/A, 30.293600, 120.161400, 0, 0 | 1281 |
CN, 22, Beijing, Beijing, N/A, 39.928902, 116.388298, 0, 0 | 1481 |
CN, 04, Jiangsu, Nanjing, N/A, 32.061699, 118.777802, 0, 0 | 1595 |
CN, 10, Hebei, Hebei, N/A, 39.889702, 115.275002, 0, 0 | 1602 |
CN, 12, Hubei, Wuhan, N/A, 30.580099, 114.273399, 0, 0 | 1753 |
TR, N/A, N/A, N/A, N/A, 41.021400, 28.994801, 0, 0 | 2709 |
PL, 78, Mazowieckie, Warsaw, 03-428, 52.250000, 21.000000, 0, 0 | 17871 |
Conclusion
This time, exploring the SSH log with geoiplookup
mapped IP
addresses to physical locations and how many times SSH daemon rejected
login attempts.
If there is a server openly accessible on the Internet, find a way to lock it down! If it can be accessed, someone, somewhere will try!
Next time, I will talk about using Fail2Ban to reduce continued failed access.