0x00 前言
Linux系统拥有非常灵活和强大的日志功能,可以保存几乎所有的操作记录,并可以从中检索出我们需要的信息。 本文简介一下Linux系统日志及日志分析技巧。
0x01 日志简介
1.1 日志服务
syslogd
介绍
说到 Linux 的日志,就不得不提到 syslogd
。它是大部分 Linux 发行版默认的日志守护进程,是一个记录日志的服务,子配置文件位于 /etc/syslog
或 /etc/syslogd
,默认配置文件为 /etc/syslog.conf
。从架构来看,这个服务下面有一系列的子服务,例如 mail、cron 等等,这些子服务对外提供日志记录的功能,当其它的程序或服务需要记录日志的时候,就可以直接调用这些子服务将日志记录到指定的地方。
我们编写的代码可以通过 syslog 的接口进行 log,syslog 会通过 socket 将 log 发送给 syslogd,syslogd 在获取到 log 后,会对 log 进行处理,然后根据用户配置,将 log 保存到本地或者发送到其他服务器上去。
最简单的,用 logger -t '[test]' "I'm zinc"
就可以直接日志记录到 message 里:
再举个 python 使用 syslog 的例子吧:
In [1]: import syslog
In [2]: syslog.openlog('[test]')
In [3]: syslog.syslog("I'm zinc")
PYTHON
然后就可以在 /var/log/messages
里面看到它了:
配置文件详解
作为 syslogd 的配置文件,syslog.conf
指定了:
- 什么服务?
- 什么日志等级?
- 记录在哪里?
格式如下:
服务名称+条件运算符+信息等级 日志保存的位置
具体来说:
-
服务名称
- user:默认值
- auth/authpriv:主要是与认证有关的服务的日志,例如 login、ssh、su 等
- cron:定时任务的日志,包括 cron 和 at
- kern:即 kernel(用户进程是无法生成这种日志的)
*
:代表任意服务- ...
举例来说, sendmail 与 postfix 都会通过 syslog 记录日志,服务名称为 LOG_MAIL,所以它们产生的日志在 syslogd 看来就都是 mail 类型的。
-
条件运算符
.
:即>=
,大于等于该等级的日志都要记录下来.=
:即==
,等于该等级的日志都要记录下来.!
:即!=
,除了该等级的日志都要记录下来
-
信息等级
- debug:debug 级别的日志,一般用于调试
- info:仅是一些基本的信息说明
- notice:有些信息需要强调一下
- warning:警示,可能会出问题。这个层级以及以下的,基本无需处理,知道就行。
- err:错误信息,导致程序/系统无法运行
- crit:出现了很严重的错误
- alert:出现了非常严重的错误,必须马上解决
- emerg:系统已经无法使用了
- none:无优先级
*
:任意优先级
-
日志保存的位置:通常是保存在本地文件里。当然也可以选择发送给指定的日志服务器保存。
最后还有 2 点需要注意:
-
多个服务,不同等级,要共用记录位置的话,可以用
;
来合并:
# 表示 auth 的和 cron 的全部等级的日志都记录在 important 里 # 然后再存一份它们 warn 等级的日志在 important.warn 里 auth.*;cron.* /var/log/important auth.=warn;cron.=warn /var/log/important.warn AWK
-
多个服务,共用等级的话,可以用
,
来合并:
# 表示所有日志都存在 messages 里 # 然后通过设定 auth、cron 的日志等级为 none 来阻止它们记录日志 *.*;auth,cron.none /var/log/messages # 当然这样也是可以的 *.*;auth.none;cron.none /var/log/messages
rsyslogd
目前不少的 Linux 发行版已经用 rsyslogd 代替了 syslogd。rsyslogd 是 syslogd 的升级版,子配置文件位于 /etc/rsyslog.d
,默认配置文件为 /etc/rsyslog.conf
,由于其配置语法与 syslogd 的配置文件一致,这里就不重复说了。
那么在说各个具体的系统日志之前,我们先来看看 rsyslogd 的配置。因为有些系统日志是通过 rsyslogd 记录的,那么正如前面说的,rsyslog.conf 就决定了这些系统日志存放的位置。
如果你在网上搜索 “linux ssh 日志位置”,很大概率会告诉你是 /var/log/secure
。但是这个其实是默认位置,是有可能被改掉的(不同发行版或者是恶意修改)。所以不管是应急也好,做威胁检测也好,最好要通过 rsyslog.conf 来确定特定系统日志真正的位置。
比如这是我虚拟机的配置:
这下我们才可以确定,messages 存放了除了 mail、authpriv、cron 之外所有的 info 等级的日志(所以这个日志文件通常是比较大的);authpriv 存在 secure 里;cron 存在 cron 里。
最后有两个小经验:
- 如果攻击者把这类日志删除了的话,那么只要 rsyslogd 进程没有停止过(重启也算停止过),就可以从
/proc/pid/fd/n
(pid 和 n 取决于实际情况)恢复日志。步骤非常简单,先用sudo lsof +L1
看一下有没有被删除的 log 文件,有的话记下 pid,然后ls -l /proc/pid/fd
找一下日志文件是对应的哪个 fd,直接 cp 即可 - 如果用 vim 打开了通过 rsyslogd 记录的日志的文件之后,执行了保存操作(打开后直接 wq 也算),那么该日志会立即停止记录。回想一下 vim 的 wq 原理,其实就是 cp+mv,cp 不用说,会创建一个新的 inode;mv 的文件在同一个分区下时,执行的其实是 rename;这一套流程下来,在
/proc/pid/fd/n
下面的表现就是后面多了一个(deleted)
(这里面的机制有些复杂,不仅仅是 inode 那么简单的,有机会的话详细介绍)。如果要恢复中断的记录,那么就需要从/proc/pid/fd/n
下面 cp 出来,然后重启 rsyslogd;如果不想找回中断的记录,那么直接重启就行
1.2 常用日志
日志默认存放位置:/var/log/
查看日志配置情况:more /etc/rsyslog.conf
日志文件 | 说明 |
---|---|
/var/log/cron | 记录了系统定时任务相关的日志 |
/var/log/cups | 记录打印信息的日志 |
/var/log/dmesg | 记录了系统在开机时内核自检的信息,也可以使用dmesg命令直接查看内核自检信息 |
/var/log/mailog | 记录邮件信息 |
/var/log/message | 记录系统重要信息的日志。这个日志文件中会记录Linux系统的绝大多数重要信息,如果系统出现问题时,首先要检查的就应该是这个日志文件 |
/var/log/btmp | 记录错误登录日志,这个文件是二进制文件,不能直接vi查看,而要使用lastb命令查看 |
/var/log/lastlog | 记录系统中所有用户最后一次登录时间的日志,这个文件是二进制文件,不能直接vi,而要使用lastlog命令查看 |
/var/log/wtmp | 永久记录所有用户的登录、注销信息,同时记录系统的启动、重启、关机事件。同样这个文件也是一个二进制文件,不能直接vi,而需要使用last命令来查看 |
/var/run/utmp | 记录当前已经登录的用户信息,这个文件会随着用户的登录和注销不断变化,只记录当前登录用户的信息。同样这个文件不能直接vi,而要使用w,who,users等命令来查询 |
/var/log/secure | 记录验证和授权方面的信息,只要涉及账号和密码的程序都会记录,比如SSH登录,su切换用户,sudo授权,甚至添加用户和修改用户密码都会记录在这个日志文件中 |
1.3 比较重要的几个日志:
messages
默认路径:/var/log/messages
它是默认的日志文件,记录 Linux 内核消息及各种应用程序的日志信息,包括:启动、IO 错误、网络错误、程序自定义日志等等。
虽然信息种类会多一些,但是这个一般用得少,就不多说了。
secure
默认路径:/var/log/secure
只要牵涉到需要输入帐号密码的程序,包括 login、有图形界面的 Linux 登录的时候、su、sudo、ssh、telnet、groupadd、useradd、passwd 等等,那么当登录时(不管成功或者失败)都会被记录在此。
secure 是应急响应中最常查看的文件,例如疑似存在 ssh 爆破的时候,我们就可以查看这个文件,这类应急基本上是在考验我们使用 grep、awk、sed 的熟练度。
cron
默认路径:/var/log/cron
该日志文件记录了 cron 运行的日志。包含:
- crontab 运行定时任务的记录,包含运行的命令、时间、pid、定时任务所属的用户等
- 更新定时任务(关键字 REPLACE/RELOAD)的时间点与用户
- 如果定时任务有直接输出的话,也会打到 cron 里去
cron 的作用比较专一,它一般有两种用途:
- cron 误删之后,可以根据日志直接恢复命令;至于定时任务的调度周期,可以尝试根据定时任务通过每次执行的间隔来尝试还原。
- 如果 crontab 被植入了恶意的定时任务,那么在这里可以找到植入后第一次运行的时间,结合调度周期,可以推断出被植入的时间范围。
1.4 登录相关日志
先来看一下整体的流程。
在 Linux 中,每当有一个用户登录时,如果有分配 tty,login 命令要负责:
- 在文件 lastlog 中查看用户的 UID,如果存在,则把用户上次登录、注销的时间和主机名写到标准输出中
- 然后在 lastlog 日志中记录新的登录时间
- 接着在 utmp 日志中记录用户新的登陆记录
- 接着在 wtmp 日志中记录用户新的登陆记录
- 当用户登录退出时
- 在 wtmp 日志中记录用户新的注销记录
- 最后在 utmp 日志中删除该用户对应的登陆记录
接下来详细看一下每个日志的用途,这些日志都是二进制格式的日志,用 cat、less 是看不了的。btmp、utmp 和 wtmp,它们的数据结构是一样的,而 lastlog 文件有自己的数据结构,关于它们的具体的数据结构可以使用 man 命令查询,例如 man utmp
。
lastlog
默认路径:/var/log/lastlog
该日志文件记录了每个用户最近一次成功的登录事件和最后一次不成功的登录事件,每次用户登录的时候都会查一下这个日志的记录。
一般用 lastlog
命令查看,会根据 UID 排序来显示用户名、tty、IP 和最后登录时间,如果某用户从来没有登录过,就显示为 **Never logged in**
:
wtmp
默认路径:/var/log/wtmp
该日志文件记录了每个用户登录、注销及系统的重启等事件,主要用于查看用户的登录记录。
一般用 last
命令查看,会以反序从后向前显示用户的登录记录,也能根据用户名、tty 或时间显示相应的记录:
utmp
默认路径:/var/run/utmp
该日志文件记录了当前登录的每个用户的信息。因此这个文件会随着用户登录、注销而不断变化,因为它只保留了当前已登录的用户记录,不会为用户保留永久的记录。
系统中需要查询当前用户状态的程序,如 who、w、users、finger 等其实就是从这个文件获取的信息:
btmp
默认路径:/var/log/btmp
该日志文件记录了失败的登录尝试。默认没有初始化,不会记录,可以执行一次 lastb
开始记录。
一般用 lastb
命令查看:
1.5 查看日志的一些方法:
①lastlog:
列出所有用户最近登录的信息,或者指定用户的最近登录信息。lastlog引用的是/var/log/lastlog文件中的信息,包括login-name、port、last login time
② last:
列出当前和曾经登入系统的用户信息,它默认读取的是/var/log/wtmp文件的信息。输出的内容包括:用户名、终端位置、登录源信息、开始时间、结束时间、持续时间。注意最后一行输出的是wtmp文件起始记录的时间。当然也可以通过last -f参数指定读取文件,可以是/var/log/btmp、/var/run/utmp。
③ lastb
列出失败尝试的登录信息,和last命令功能完全相同,只不过它默认读取的是/var/log/btmp文件的信息。当然也可以通过last -f参数指定读取文件,可以是/var/log/btmp、/var/run/utmp
(fscan模拟一下爆破)
④ ac
输出所有用户总的连接时间,默认单位是小时。由于ac是基于wtmp统计的,所以修改或者删除wtmp文件都会使ac的结果受影响。(Suse默认没有该命令)
⑤ who
查看当前登入系统的用户信息。其中who -m等效于who am i。
语法who [OPTION]… [ FILE | ARG1 ARG2 ]。
who命令强大的一点是,它既可以读取utmp文件也可以读取wtmp文件,默认没有指定FILE参数时,who查询的是utmp的内容。当然可以指定FILE参数,比如who -aH /var/log/wtmp,则此时查看的是wtmp文件。
查看当前运行级别:
查看登录用户和用户数≈users
⑥ w
查看当前登入系统的用户信息及用户当前的进程(而who命令只能看用户不能看进程)。该命令能查看的信息包括字系统当前时间,系统运行时间,登陆系统用户总数及系统1、5、10分钟内的平均负载信息。后面的信息是用户,终端,登录源,login time,idle time,JCPU,PCPU,当前执行的进程等。
w的信息来自两个文件:用户登录信息来自/var/run/utmp,进程信息来自/proc/.
⑦ users
显示当前正在登入统的用户名。语法是users [OPTION]… [FILE]。如果未指定FILE参数则默认读取的是/var/run/utmp,当然也可以指定通用相关文件/var/log/wtmp,此时输出的就不是当前用户了。
0x02 日志分析技巧
A、常用的shell命令
Linux下常用的shell命令如:find、grep 、egrep、awk、sed
小技巧:
1、grep显示前后几行信息:
标准unix/linux下的grep通过下面參数控制上下文:
grep -C 5 foo file 显示file文件里匹配foo字串那行以及上下5行
grep -B 5 foo file 显示foo及前5行
grep -A 5 foo file 显示foo及后5行
查看grep版本号的方法是
grep -V
2、grep 查找含有某字符串的所有文件
grep -rn "hello,world!"
* : 表示当前目录所有文件,也可以是某个文件名
-r 是递归查找
-n 是显示行号
-R 查找所有文件包含子目录
-i 忽略大小写
3、如何显示一个文件的某几行:
cat input_file | tail -n +1000 | head -n 2000
#从第1000行开始,显示2000行。即显示1000~2999行
4、find /etc -name init
//在目录/etc中查找文件init
5、只是显示/etc/passwd的账户
`cat /etc/passwd |awk -F ':' '{print $1}'`
//awk -F指定域分隔符为':',将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。
6、sed -i '153,$d' .bash_history
删除历史操作记录,只保留前153行
B、日志分析技巧
A、/var/log/secure
1、定位有多少IP在爆破主机的root帐号:
grep "Failed password for root" /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -nr | more
定位有哪些IP在爆破:
grep "Failed password" /var/log/secure|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"|uniq -c
爆破用户名字典是什么?
grep "Failed password" /var/log/secure|perl -e 'while($_=<>){ /for(.*?) from/; print "$1\n";}'|uniq -c|sort -nr
2、登录成功的IP有哪些:
grep "Accepted " /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -nr | more
登录成功的日期、用户名、IP:
grep "Accepted " /var/log/secure | awk '{print $1,$2,$3,$9,$11}'
3、增加一个用户kali日志:
Jul 10 00:12:15 localhost useradd[2382]: new group: name=kali, GID=1001
Jul 10 00:12:15 localhost useradd[2382]: new user: name=kali, UID=1001, GID=1001, home=/home/kali
, shell=/bin/bash
Jul 10 00:12:58 localhost passwd: pam_unix(passwd:chauthtok): password changed for kali
#grep "useradd" /var/log/secure
4、删除用户kali日志:
Jul 10 00:14:17 localhost userdel[2393]: delete user 'kali'
Jul 10 00:14:17 localhost userdel[2393]: removed group 'kali' owned by 'kali'
Jul 10 00:14:17 localhost userdel[2393]: removed shadow group 'kali' owned by 'kali'
# grep "userdel" /var/log/secure
5、su切换用户:
Jul 10 00:38:13 localhost su: pam_unix(su-l:session): session opened for user good by root(uid=0)
sudo授权执行:
sudo -l
Jul 10 00:43:09 localhost sudo: good : TTY=pts/4 ; PWD=/home/good ; USER=root ; COMMAND=/sbin/shutdown -r now
- 这里不太完整 后面用到了再补回来
参考连接: