使用 Perl 总结 Linux 上的安全日志文件





0/5 (0投票)
快速总结 Linux 系统上的安全日志文件,

引言
任何服务器管理员都知道,确保服务器安全是他们工作中最重要的事情之一。Linux 是一种流行的服务器操作系统,它具有可扩展性、可扩展性,并且广泛用于托管和其他用途。几乎所有的 Linux 系统都使用一种称为 ssh 的工具进行远程管理。ssh 是 Secure shell 的缩写,它允许客户端和服务器之间进行完全安全的安全通信,从而从命令行管理服务器。
注意:您还可以进行端口转发(本文不介绍,可能在以后的文章中介绍...),它允许您通过 ssh "隧道"转发不安全的协议(如 FTP,或我喜欢的:远程 VNC),从而有效地将任何不安全的协议转换为安全的协议。
总之,ssh 通常使用端口 22。有些人会将其更改为非标准端口,以便 "坏人" 可能不会认为他们的服务器上运行着 ssh。然而,大多数人仍然使用默认端口。人们编写脚本来查找开放端口 22 的服务器,然后开始尝试猜测用户名和密码来破解服务器,这是非常普遍的。每一次失败和成功的登录尝试都会记录在 "/var/log/secure" 文件中。这是一个相对简单的 Perl 脚本,它解析这个(可能非常长的)日志文件,总结其中的信息并将其显示给您。
背景
我最初是为上学期的一门 Perl 编程课程写的。然而,在我工作学习的岗位上,我做了很多服务器管理工作,我觉得有必要看看我服务器上的登录失败尝试。如果您认为我开玩笑,说这是个多么严重的问题,这是我刚运行的脚本的输出的最后一部分:
SUCCESS - klschaefer attempted 10 times
Results:
(Failed due to bad password: 714)
Failed due to bad user: 8560
+______________
Number of Failed Login Attempts: 9274
Number of Successful Login Attempts: 10
正如您所看到的,我登录到服务器 10 次(我的用户名是 "klschaefer"),总共有 8560 次失败的登录尝试。现在,诚然,即使是比较好的密码也足以不用担心这些尝试。但如果您是那种使用 "password"、"i_love_cheese"、"1234" 或 "(使用与用户名相同的密码)" 这种密码的人,您可能需要重新考虑您的密码。
另一个需要注意的重要事项是:每个 Linux 服务器都有一个名为 "root" 的管理员 "超级用户" 帐户。这是每个 Linux 系统上唯一保证存在的用户帐户。因此,可以肯定地说,大约一半的攻击是为了猜测 root 的密码。另一半是为了随机用户帐户。他们不都针对 root 的原因在于,通常情况下,服务器管理员会有一个相当不错的密码,而普通用户可能不会。以我们学校系里的一台服务器为例。所有参加某些编程课程的学生都在这台服务器上有帐户,可以在上面进行任何他们需要的开发。我确切地知道,其中一些人没有更改他们的默认密码(一个 7 位数的学生 ID),还有几个人使用了常见的字典单词。因此,有人可能会轻易地破解这台服务器上某个学生帐户。
Using the Code
在深入探讨之前,有一点需要说明:如果您对正则表达式了解不多,可能会在这篇文章中感到困惑。我建议您阅读一下这方面的资料,或者在看到时查阅快速参考指南。Perl(以及 Javascript 等)中的正则表达式是用正斜杠 "/" 来界定的。所以,这是一个正则表达式:"/^[Ii]nvalid\suser\s(\w+)\sfrom\s(\d+\.\d+\.\d+\.\d+)/"。不要害怕,它们是我学习 Perl 最困难的部分,但一旦您学会了它们,下面的代码就没那么复杂了。
有三个基本文件:"/var/log/secure"、"secure.pl" 和一个 "secure_out.log" 文件(由脚本生成)。这不是一个 Perl 教程,所以我假设您可以弄清楚代码是如何工作的,但我会解释其中的一些。首先,我们将打开文件并定义我们需要跟踪所有内容的变量。
open LOG, "</var/log/secure";
open OUT, ">secure_out.log";
my $failedCount = 0; # number of bad logins from any user
my $successCount = 0; # number of successful logins from any user
my $badUserCount = 0; # number of bad users
my $badPasswordCount = 0; # number of bad passwords, excludes bad users
my %ips;
my %users;
my %successful;
my %failed;
第一组变量是简单的计数器。第二组(注意 "%" 符号)是 **哈希**,我们用它们将某些 **键** 与相应的 **值** 关联起来(例如,123.456.789.012 有 7 次登录失败尝试,或者 "klschaefer" 成功登录了 4 次,等等)。接下来,我们打开日志文件,每次迭代读取一行。下面的代码位于循环内部。首先,我们忽略注释行(任何以井号 "#" 开头的行),然后开始检查每一行代表什么。
#first, ignore comment lines
next if ($line =~ /\s*#/);
if($line =~ /[Ii]nvalid\suser\s(\w+)\sfrom\s(\d+\.\d+\.\d+\.\d+)/)
{
print OUT "Invalid user: $1 from IP: $2\n";
if(exists $ips{$2})
{
$ips{$2}++;
}
else
{
$ips{$2} = 1;
}
if(exists $users{$1})
{
$users{$1}++;
}
else
{
$users{$1} = 1;
}
if(exists $failed{$1})
{
$failed{$1}++;
}
else
{
$failed{$1} = 1;
}
$failedCount++;
$badUserCount++;
}
上面的代码段检查该行是否代表一个无效用户(例如,服务器上根本不存在的用户)。由于我们使用的是哈希,我们必须首先检查一个键是否已经存在,如果存在,我们就可以递增它,否则我们就创建一个新项并将其设置为 1。
接下来,这里是其余的检查。
elsif($line =~ /[Ff]ailed\spassword\sfor\s(\w+)\sfrom\s(\d+\.\d+\.\d+\.\d+)/)
{
print OUT "Bad password for user: $1 from IP: $2\n";
if(exists $ips{$2})
{
$ips{$2}++;
}
else
{
$ips{$2} = 1;
}
if(exists $users{$1})
{
$users{$1}++;
}
else
{
$users{$1} = 1;
}
if(exists $failed{$1})
{
$failed{$1}++;
}
else
{
$failed{$1} = 1;
}
$failedCount++;
$badPasswordCount++;
}
elsif($line =~ /[Aa]ccepted\spassword\sfor\s(\w+)\sfrom\s(\d*\.\d*\.\d*\.\d*)/
|| $line =~ /[Aa]ccepted\spublickey\sfor\s(\w+)\sfrom\s(\d*\.\d*\.\d*\.\d*)/)
{
print OUT "Successful Login for User: $1 from IP: $2\n";
if(exists $ips{$2})
{
$ips{$2}++;
}
else
{
$ips{$2} = 1;
}
if(exists $users{$1})
{
$users{$1}++;
}
else
{
$users{$1} = 1;
}
if(exists $successful{$1})
{
$successful{$1}++;
}
else
{
$successful{$1} = 1;
}
$successCount++;
}
因此,我们像这样检查日志文件的每一行,递增相应的计数器,现在我们需要显示结果。
while(($ip, $count) = each %ips)
{
print "LOGIN - $ip attempted $count times\n";
}
while(($user, $count) = each %users)
{
print "LOGIN - $user attempted $count times\n";
}
while(($user, $count) = each %failed)
{
print "FAILED - $user attempted $count times\n";
}
while(($user, $count) = each %successful)
{
print "SUCCESS - $user attempted $count times\n";
}
print <<END_OF_MESSAGE
Results:
(Failed due to bad password: $badPasswordCount)
Failed due to bad user: $badUserCount
+______________
Number of Failed Login Attempts: $failedCount
Number of Successful Login Attempts: $successCount
END_OF_MESSAGE
其他说明
您需要以 root 用户身份登录才能读取 /var/log/secure 文件。
将 root 的登录限制在本地机器上始终是个好主意。换句话说,您可以禁止所有人远程登录为 root。您仍然可以通过先登录到您的个人帐户,然后 "su" 进入 root 模式来获得 root 访问权限。
如果您想查看更详细的失败和成功登录列表,只需打开 "secure_out.log" 文件。
最后,脚本可能会生成过多的输出,您可能无法全部看到,因此您可能需要将其通过管道传递给 "less
"(例如:"./secure.pl | less
")。
历史
- 2011/12/20:初稿