5

ssh 密码暴力破解是很常见的一种攻击。每个开启了 ssh 密码登录公网服务器几乎都会被攻击。本文使用 linux 自带的工具简单分析了 auth 日志,用非常简单的方法查找了攻击者的 ip、ip 地理位置、被攻击的用户名,被攻击的次数等信息。

我们有一台服务器在公网上,密码比较弱,我记得一配好就关闭了 ssh 密码登录了,结果昨天偶然发现密码登录居然还开着。赶紧看了一下系统认证日志,发现已有十几万次错误的密码尝试了。

记录一下过程。

我这里是 ubuntu 系统 auth 日志默认在 /var/log/auth.log(有的系统默认在 /var/log/secure 但是格式可能不一样,想确定具体位置看文末更多细节,最近更新补充了 centos 的命令,见文末)

还有文章提到的一些命令的使用方法简介也在文末更多细节中

简单分析日志内容

日志条数

wc -l /var/log/auth.log
66915 /var/log/auth.log

这里有 6 万多条记录。

grep "Failed password" /var/log/auth.log | wc -l
19128

密码验证失败有 19128 次

查看所有密码认证成功记录

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,说明最近应该没有别人登录成功过。

查看所有 auth 日志文件

ls /var/log/auth.log* -lht

<pre>-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 <font color="#FF5555">/var/log/auth.log.2.gz</font>
-rw-r----- 1 syslog adm 1.6M Jan 27 14:25 <font color="#FF5555">/var/log/auth.log.3.gz</font>
-rw-r----- 1 syslog adm 927K Jan 19 14:25 <font color="#FF5555">/var/log/auth.log.4.gz</font>
</pre>

可以看到系统目前产生了 5 个日志文件了。刚刚看的 auth.log 文件只是最近的日志。

可以把这几个文件放到一起分析所有日志的内容。

使用 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 列是攻击者尝试的用户名。

把日志文件放到一起并解压

mkdir authlog
cd authlog
cp /var/log/auth.log* .
gunzip auth.log.*.gz

统计攻击者 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
3298

一共有 3298 个 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.* | 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

最多的一个 ip 攻击了 23755 次

保存到文件

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

查看攻击者 ip 地理位置

这里我们使用了 ipip.net 的免费 api。ipip.net 很好用。(这免费 api 有调用次数限制)

看刚刚保存的 ip.log 文件里前 10 条

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
["中国","上海","上海","","电信/联通/移动"]

攻击者尝试的用户名

查看条数

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
5627

它们试了 5000 多个用户名

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

关闭 ssh 密码登录

vi /etc/ssh/sshd_config

找到

#PasswordAuthentication yes

改成

PasswordAuthentication no

然后重启 sshd

service sshdrestart (systemd 的命令是 systemctl reload sshd

更多细节

查看日志位置

一般来说 ubuntu 在 /var/log/auth.log centos 在 /var/log/secure 这两者格式不一样。

具体在什么位置是在 rsyslog 的配置文件里:/etc/rsyslog.conf 或者 /etc/rsyslog.d (当然你的系统必须是用 rsyslog 的才行,如果不是用这个就不在这里,使用命令 ps aux | grep "rsyslog" | grep -v "grep" 看系统里有没有 rsyslog 进程可以判断系统是否使用 rsyslog)

ubuntu 18.04

auth,authpriv.* /var/log/auth.log
具体位置是 /etc/rsyslog.d/50-default.conf

CentOS 7.6

# The authpriv file has restricted access.
authpriv.* /var/log/secure
具体位置是 /etc/rsyslog.conf

命令:
查看成功登录

grep "Accepted password for" /var/log/secure

查看每个用户名失败的次数

grep "Failed password"  /var/log/secure | awk '{if (NF==16){c[$11]++}else{c[$9]++}}END{for(u in c)print u,c[u]}' | sort -k 2 -nr | head

查看每个 IP 地址失败的次数

grep "Failed password"  /var/log/secure | awk '{if (NF==16){c[$13]++}else{c[$11]++}}END{for(u in c)print u,c[u]}' | sort -k 1 -n  | head

用到的命令简介

awk

强大的流编辑工具,有自己的一套语言。(功能强大,比 python 更加简洁)

system 函数用于在 awk 中执行 shell 命令。

我收集的一些常用的脚本:

awk输出两个文件不同的行

awk 随机抽样文件

sort

-n 作为数字进行排序

-k 指定排序的列

-r 参数倒序

另外还有

-t 指定分隔符,如果要指定 t 可用 sort -t $'\t' 或者 -t'\<ctrl>v\<tab>'

-u 排序后去重

欢迎关注我的博客 https://codeplot.top/


sxwxs
292 声望20 粉丝

计算机专业学生