本文转载于 SegmentFault 社区
社区专栏:我的专栏
作者:sxwxs
ssh 密码暴力破解是很常见的一种攻击。每个开启了 ssh 密码登录公网服务器几乎都会被攻击。本文使用 linux 自带的工具简单分析了 auth 日志,用非常简单的方法查找了攻击者的 ip、ip 地理位置、被攻击的用户名,被攻击的次数等信息。
我们有一台服务器在公网上,密码比较弱,我记得一配好就关闭了 ssh 密码登录了,结果昨天偶然发现密码登录居然还开着。赶紧看了一下系统认证日志,发现已有十几万次错误的密码尝试了。
我这里是 ubuntu 系统 auth 日志默认在 /var/log/auth.log
(有的系统默认在 /var/log/secure 但是格式可能不一样,想确定具体位置看文末更多细节)
还有文章提到的一些命令的使用方法简介也在文末更多细节中
1. 日志条数
grep "Failed password" /var/log/auth.log | wc -l
2. 查看所有密码认证成功记录
grep "password" /var/log/auth.log | grep -v Failed | grep -v Invalid
Feb 14 09:59:50 server sshd[19695]: Accepted password for xxx from 59.xx.xx.xx port 40932 ssh2
Feb 14 10:00:32 server sshd[19929]: Accepted password for xxx from 59.xx.xx.xx port 40934 ssh2
Feb 14 10:07:29 server sshd[20121]: Accepted password for xxx from 59.xx.xx.xx port 40948 ssh2
只有三条都是我自己的 ip,说明最近应该没有别人登录成功过。
3. 查看所有 auth 日志文件
ls /var/log/auth.log* -lht
-rw-r----- 1 syslog adm 7.5M Feb 15 09:40 /var/log/auth.log
-rw-r----- 1 syslog adm 7.6M Feb 10 14:25 /var/log/auth.log.1
-rw-r----- 1 syslog adm 1.1M Feb 2 14:25 /var/log/auth.log.2.gz
-rw-r----- 1 syslog adm 1.6M Jan 27 14:25
/var/log/auth.log.3.gz
-rw-r----- 1 syslog adm 927K Jan 19 14:25
/var/log/auth.log.4.gz
可以看到系统目前产生了 5 个日志文件了。刚刚看的 auth.log 文件只是最近的日志。
4. 使用 awk 简单汇总信息
但是主要有两种情况,一种是用户不存在,一种是用户存在。
cat /var/log/auth.log| grep "Failed password"|head -1 | awk '{while($i){print i, $i;i++}}'
Feb 10 06:25:02 server sshd[3792]: Failed password for root from 118.xx.xx.xx port 49074 ssh2
1 Feb
2 10
3 06:25:02
4 server
5 sshd[3792]:
6 Failed
7 password
8 for
9 root
10 from
11 118.25.39.242
12 port
13 49074
14 ssh2
第 11 列是 ip,第 9 列是攻击者尝试的用户名。
cat /var/log/auth.log| grep "Failed password"
| grep invalid |head -1 | awk '{while($i){print i, $i;i++}}'
Feb 10 06:25:19 server sshd[3936]: Failed password for invalid user ubuntu from 118.xx.xx.xx port 49842 ssh2
1 Feb
2 10
3 06:25:19
4 server
5 sshd[3936]:
6 Failed
7 password
8 for
9 invalid
10 user
11 ubuntu
12 from
13 118.25.39.242
14 port
15 49842
16 ssh2
第 13 列是 ip,第 11 列是攻击者尝试的用户名。
5. 把日志文件放到一起并解压
mkdir authlog
cd authlog
cp /var/log/auth.log* .
gunzip auth.log.*.gz
6. 统计攻击者 ip
awk '{if($6=="Failed"&&$7=="password"){if($9=="invalid"){ips[$13]++;users[$11]++}else{users[$9]++;ips[$11]++}}}END{for(ip in ips){print ip, ips[ip]}}' auth.* | wc -l
1)按攻击次数排序
awk '{if($6=="Failed"&&$7=="password"){if($9=="invalid"){ips[$13]++;users[$11]++}else{users[$9]++;ips[$11]++}}}END{for(ip in ips){print ip, ips[ip]}}' auth.* | sort -k2 -rn | head
118.201.74.xx 23755
118.27.3.xx 11878
118.25.41.xx 11878
118.25.208.xx 11878
118.25.20.xx 11878
118.25.26.xx 11877
118.89.16.xx 11876
118.24.121.xx 10905
111.13.139.xx 5702
118.25.39.xx 5065
2)保存到文件
awk '{if($6=="Failed"&&$7=="password"){if($9=="invalid"){ips[$13]++;users[$11]++}else{users[$9]++;ips[$11]++}}}END{for(ip in ips){print ip, ips[ip]}}' auth.* | sort -k2 -rn > ip.log
这里我们使用了 ipip.net 的免费 api。ipip.net 很好用。
(这免费 api 有调用次数限制)
head -10 ip.log | awk '{print $1" ";system("curl http://freeapi.ipip.net/"$1);print("\n")}'
118.201.74.xxx
["新加坡","新加坡","","","singtel.com"]
118.27.3.xxx
["日本","东京都","东京","","gmo.jp"]
118.25.41.xxx
["中国","上海","上海","","电信/联通/移动"]
118.25.208.xxx
["中国","四川","成都","","电信/联通/移动"]
118.25.20.xxx
["中国","上海","上海","","电信/联通/移动"]
118.25.26.xxx
["中国","上海","上海","","电信/联通/移动"]
118.89.16.xxx
["中国","广东","广州","","电信/联通/移动"]
118.24.121.xxx
["中国","四川","成都","","电信/联通/移动"]
111.13.139.xxx
["中国","北京","北京","","移动"]
118.25.39.xxx
["中国","上海","上海","","电信/联通/移动"]
7. 攻击者尝试的用户名
awk '{if($6=="Failed"&&$7=="password"){if($9=="invalid"){ips[$13]++;users[$11]++}else{users[$9]++;ips[$11]++}}}END{for(user in users){print user, users[user]}}' auth.* | sort -k2 -rn |wc -l
awk '{if($6=="Failed"&&$7=="password"){if($9=="invalid"){ips[$13]++;users[$11]++}else{users[$9]++;ips[$11]++}}}END{for(user in users){print user, users[user]}}' auth.* | sort -k2 -rn | head
root 120711
admin 1443
test 426
user 397
postgres 245
oracle 241
ubuntu 221
guest 211
nagios 207
git 191
其中 root 试了 12 万次。但是我的 root 是 ubuntu 默认的随机密码,我就没有动过,我自己都不知道密码是啥。
而 admin 和 test 这些用户我的系统里都不存在。所以他绝大多数努力都是无用功。
保存到文件
awk '{if($6=="Failed"&&$7=="password"){if($9=="invalid"){ips[$13]++;users[$11]++}else{users[$9]++;ips[$11]++}}}END{for(user in users){print user, users[user]}}' auth.* | sort -k2 -rn > username.log
#PasswordAuthentication yes
PasswordAuthentication no
service sshdrestart
(systemd 的命令是
systemctl reload sshd