安全运维之如何将Linux历史命令记录发往远程Rsyslog服务器首席安全官频道

* 本文作者:knpewg85942,首席安全官频道本文属FreeBuf原创奖励计划,未经许可禁止转载

0×01. 前言

在谁动了我的主机? 之活用History命令|Linux安全运维一文中,作者已经演示了如何将history 命令记录发往本地Rsyslog,本文会介绍将Linux history 记录发往远程Rsyslog 服务器的2种方法。

0×01. 方法1,修改bash源码,使其支持将history历史记录发往远程Rsyslog 服务器

从bash4.1 版本开始,bash开始支持Rsyslog,所以我们需要下载bash4.1以后版本,这里以bash4.4为例

bash源码下载地址:  https://ftp.gnu.org/gnu/bash/

共计需要修改两处源码:

1) 先修改bashhist.c

从源码文件名字也可以看出这个源码文件和linux history记录处理有关

748 #if defined (SYSLOG_HISTORY)

    749 #define SYSLOG_MAXLEN 600

    750 

    751 extern char *shell_name;

    752 

    753 #ifndef OPENLOG_OPTS

    754 #define OPENLOG_OPTS 0

    755 #endif

    756 

    757 void

    758 bash_syslog_history (line)

    759      const char *line;

    760 {

    761   char trunc[SYSLOG_MAXLEN];

    762   static int first = 1;

    763 

    764   if (first)

    765     {

    766       openlog (shell_name, OPENLOG_OPTS, SYSLOG_FACILITY);

    767       first = 0;

    768     }

    769 

    770   if (strlen(line) < SYSLOG_MAXLEN)

    771     syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d User=%s CMD=%s", getpid(), current_user.uid, current_user.user_name, line);

    772   else

    773     {

    774       strncpy (trunc, line, SYSLOG_MAXLEN);

    775       trunc[SYSLOG_MAXLEN - 1] = '\0';

    776       syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d UID=%d User=%s CMD=%s", getpid(), current_user.uid, current_user.user_name, trunc);

    777     }

    778 }

    779 #endif

需要修改771行和776行,修改内容,如上所示

其中PID表示当前执行linux命令的bash进程ID,使用函数getpid()获取;UID表示执行命令用户的ID,用current_user.uid 表示;User表示执行命令的用户名,用 current_user.user_name表示;CMD表示执行的历史命令内容。

2)再修改config-top.h

    116 #define SYSLOG_HISTORY

    117 #if defined (SYSLOG_HISTORY)

    118 #  define SYSLOG_FACILITY LOG_USER

    119 #  define SYSLOG_LEVEL LOG_INFO

    120 #  define OPENLOG_OPTS LOG_PID

    121 #endif

    122 

    将116行注释去掉(2个#去掉一个就好),去掉之后,如上所示  

    这里定义syslog的FACILITY为 user (用户级别的日志)

    日志级别为info

3)编译

 ./configure --prefix=/usr/local/bash && make && make install 

4) 修改/etc/passwd  修改用户的登录shell (当然也可以直接替换原先的bash)

    root:x:0:0:root:/root:/usr/local/bash/bin/bash
    f3:x:1004:1004::/home/f3:/usr/local/bash/bin/bash

5)修改/etc/rsyslog.conf

    user.info                                               @@10.1.100.1

将FACILITY 为user 且日志级别为info的信息发往 远程rsyslog 服务器 10.1.100.1

最后重启rsyslog

6) 收日志

这里远程rsyslog 日志选择windows平台的visualsyslog,下载地址为:https://github.com/MaxBelkov/visualsyslog/, 以下是收到的日志截图:

日志截图


日志截图


0×01. 方法2,不修改bash源码,利用trap和logger命令将执行命令记录发往远程Rsyslog 服务器

1) vim /etc/profile

添加以下内容

 function log2syslog

    {

       declare command

       command=$BASH_COMMAND

       logger -p local1.notice -t bash-$$ -i  -n 10.1.100.1 -- $SSH_CONNECTION---$USER---$PWD---$command

    

    }

    trap log2syslog DEBUG

解释一下:

我们知道用户登录之后shell 都会执行/etc/profile中的内容

 在shell中每执行一次命令都是一个activity,trap log2syslog DEBUG 意为对shell中的每一个activity都执行一遍log2syslog 函数

logger 是一个向syslog发送日志的接口

$BASH_COMMAND 表示 最新执行的shell命令

$$ 表示当前shell的进程id

$SSH_CONNECTION   当前ssh连接的tcp socket 五元组信息

$USER 表示当前执行命令的用户

$PWD 表示执行命令时所在目录

这些信息之间用— 隔开

-p 表示syslog的Facility

-t 表示tag

-n 表示远程syslog 地址   

2) vim /etc/rsyslog.conf

增加:

   local1.*                         @@10.1.100.1

修改配置后,重启rsyslog

3)截图

历史记录


历史记录


4) 该方法的不足

因为每记录一条命令日志到远程syslog服务器都会产生一个新的进程,如果命令activity 量很大,则相比修改bash源码方式而言比较消耗性能

如3)中截图所示,Tag中每一个bash后面中括号都表示一个新的进程id, 你可自行对比修改bash源码方式就没有此类问题

* 本文作者:knpewg85942,本文属FreeBuf原创奖励计划,未经许可禁止转载

2017-07-20 10:04 阅读:441