【企业安全实战】运维Bash命令审计

0x01 概述

Bash命令收集主要是用于在没有堡垒机和跳板机情况下实现运维操作集中审计,另外就是针对一些攻击者入侵服务器后反弹Bash或者sh等做监控。这里提供两种通过Syslog收集的方式。

0x02 通过修改Bash源码发送Syslog

从bash4.1 版本开始,bash开始支持Rsyslog,下载bash-4.4,下载地址: https://ftp.gnu.org/gnu/bash/

具体步骤如下:
1)
修改bashhist.c:
修改771行

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

修改776行

syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "PID=%d UID=%d User=%s Cmd=%s", getpid(), current_user.uid, current_user.user_name, trunc);

2)
再修改config-top.h
去掉116行/**/

#define SYSLOG_HISTORY 
#if defined (SYSLOG_HISTORY)
# define SYSLOG_FACILITY LOG_LOCAL6
# define SYSLOG_LEVEL LOG_NOTICE
# define OPENLOG_OPTS LOG_PID
#endif

syslog的FACILITY为 LOCAL6,日志级别为NOTICE
3)

./configure --prefix=/usr/local/bash && make && make install 
[root@localhost ~]# cp /bin/bash /bin/bashbak 
[root@localhost ~]# \cp -f /usr/local/bash/bin/bash /bin/bash

4)
修改rsyslog配置,这里我们先输出到本地测试一下

[root@zaojiasys_31 admin]# touch /var/log/bash.log
[root@zaojiasys_31 admin]# vim /etc/rsyslog.conf

添加local6.notice /var/log/bash.log

[root@zaojiasys_31 admin]# service rsyslog restart
[root@zaojiasys_31 admin]# tail -f /var/log/bash.log 
Jul 25 16:22:15 localhost bash[18540]: PID=18540 UID=0 User=root Cmd=tail -f /var/log/bash.log 
Jul 25 16:22:21 localhost bash[19033]: PID=19033 UID=0 User=root Cmd=whoami

5)
[root@zaojiasys_31 admin]# vim /etc/rsyslog.conf
修改*.info;mail.none;authpriv.none;cron.none;local6.none; /var/log/messages
添加local6.notice @10.110.1.33:3514

使用ELK,首先配置logstash

input {
	syslog{  
		port => "3514"  
		type => "bash"
	}  
}

filter {
    grok{
        match => {
            "message" => "PID=%{NUMBER:processid} UID=%{NUMBER:uid} User=%{WORD:user} Cmd=%{GREEDYDATA:cmd}"
        }
    }
    mutate {
        remove_field => [ "message" ]
    }
}

output {
   if "_grokparsefailure" not in [tags] {
        elasticsearch {
            hosts => "10.110.1.33:9200"
            index => "bash_%{+YYYY.MM.dd}"
        }
    }
}

Elasticsearch 添加模板

curl -XPUT 10.59.0.248:9200/_template/template_bash -d '
{
   "template": "bash_*", 
   "order" : 10,
   "settings" : {
      "number_of_shards": 5,
      "number_of_replicas": 0
   },
   "mappings" : {
    "_default_" : {
      "_all" : {"enabled" : true, "omit_norms" : true},
      "properties" : {
        "host": { "type": "keyword"},
        "cmd": { "type": "keyword"},
        "user": { "type": "keyword"},
        "uid": { "type": "integer"},
        "processid": { "type": "integer"}
      }
    }
  }
}

查看Kibana

[root@server120 ~]# ll /bin/sh
lrwxrwxrwx. 1 root root 4 3月 21 2016 /bin/sh -> bash

/bin/sh是软链到/bin/bash的,/bin/sh也可以审计到。
另外禁用其他的shell:

# chmod 750 /bin/csh
# chmod 750 /bin/tcsh
# chmod 750 /bin/dash

PS:
需要注意GLIBC的版本如果不一致的话,那么启动Bash就会有问题。

[root@localhost ~]# /bin/bash
/bin/bash: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by /bin/bash)

0x03 通过Logger发送Syslog

客户端具体配置如下:

在/etc/profile中添加行:

[ -f /etc/zb_bashrc ] && . /etc/zb_bashrc

/etc/zb_bashrc的内容如下:

if [ "$BASH" ]; then

    SSH_USER=$(who -mu  |awk '{print $1}')

    if [ -z "$SSH_USER" ]; then

        SSH_USER="-"

    fi



    SSH_CLIENT_IP=$(echo $SSH_CONNECTION |awk '{print $1}')

       if [ -z "$SSH_CLIENT_IP" ]; then

              SSH_CLIENT_IP="-"

       fi



    SSH_SERVER_IP=$(echo $SSH_CONNECTION |awk '{print $3}')

       if [ -z "$SSH_SERVER_IP" ]; then

              SSH_SERVER_IP="-"

       fi



    if [ -f "$HOME/.bash_history" ]; then

        export HISTFILE="$HOME/.bash_history"

    else

        touch $HOME/.bash_history

        chmod 600 $HOME/.bash_history

        export HISTFILE="$HOME/.bash_history"

    fi

    export HISTSIZE=100

    export HISTCONTROL=""

    export HISTIGNORE=""

    export HISTCMD

    export HISTTIMEFORMAT="%Y-%m-%d %T :: "

    PROMPT_COMMAND='history -a;history 1 | xargs -0 -i logger -p local6.notice $SSH_CLIENT_IP $SSH_SERVER_IP $SSH_USER $USER{}'

    readonly PROMPT_COMMAND

    readonly HISTTIMEFORMAT

    readonly HISTSIZE

    readonly HISTFILE

    readonly HISTIGNORE

    readonly HISTCONTROL

fi

执行source /etc/profile

修改rsysLog的配置

添加local6.notice @10.211.0.107

修改*.info;mail.none;authpriv.none;cron.none;local6.none                /var/log/messages

service rsyslog restart

 

期间遇到的问题:

1、日志重复收取

如下

增加一条配置:

$RepeatedMsgReduction on

需要注意该条配置需要放到发送syslog配置条目上面才能生效。

重复的日志会提示last message repeated X times,然后在logstash加一条配置,把该条都drop掉。

if ( "last message" in [message] ) {

       drop{}

}

最后Logstash的配置文件如下:

input {

       udp { 

          port => "514" 

          workers => "10"

       } 

}

filter {

       if ("last message" in [message]) {

              drop{}

       }

    dissect {

        mapping => {

            "message" => '<%{pri}>%{} %{} %{} %{} %{}: %{client_ip} %{server_ip} %{ssh_user} %{user}  %{line}  %{timestamp} :: %{command}'

        }

    }

       date {

           match => ["timestamp", "yyyy-MM-dd HH:mm:ss"]

           target => "@timestamp"

           "locale" => "en"

           timezone => "UTC"

       }

}

output {

       redis {

              host => "127.0.0.1"

              data_type => "list"

              key => "command"

              db => "2"

       }

}

2、sh执行命令无法记录

其实/bin/sh是软链到的/bin/bash,但是不会加载配置文件。

 

0x04 SaltStack批量部署

推荐第一种,模板如下:

install_bash:

  cmd.run:

    - name: tar zxvf bash.tar.gz && cd bash && ./configure --prefix=/usr/local/bash && make && make install

    - cwd: /root/Downloads

    - unless: test -e /usr/local/bash/bin/bash

    - require:

      - file: /root/Downloads/bash.tar.gz



/root/Downloads/bash.tar.gz:

  file.managed:

    - source: salt://audit/bash.tar.gz

    - user: root

    - group: root

    - mode: 755

    - template: jinja

    - require:

      - file: /root/Downloads



bak_bash:

  cmd.run:

    - name: cp /bin/bash /bin/bashbak

    - unless: test -e /bin/bashbak

    - require:

      - cmd: install_bash



cp_bash:

  cmd.run:

    - name: \cp -f /usr/local/bash/bin/bash /bin/bash

    - require:

      - cmd: bak_bash



/etc/rsyslog.conf:

  file.append:

    - text: "local6.notice                                               @10.59.0.58:3514"

    - unless: grep '10.59.0.58' /etc/rsyslog.conf



rsyslog:

  service.running:

    - enable: True

    - restart: True

    - watch:

      - file: /etc/rsyslog.conf

参考文章:

http://os.51cto.com/art/201102/244661.htm
http://www.freebuf.com/articles/system/140543.html
http://www.freebuf.com/articles/system/135845.html