服务器命令审计

生产服务器通常多个用户具有登录权限和操作权限。那么我们怎么需要知道这些用户登录服务器后做了哪些操作?这就需要做命令审计,即统计登录用户在服务器上执行了哪些命令。

下面是命令审计的方法:

1、创建一个配置文件,名为/etc/bash_franzi 文件内容如下:

#!/usr/bin/env bash
#Pointsoftware AG, 2013-11-03
#created by francois scheurer
#filename: ‘/etc/bash_franzi‘
#This file must be sourced by ‘~/.bashrc‘, which is the last runned startup script for bash invocation for login interactive, login non-interactive and non-login interactive shells.
#
#Having a complete history of all typed commands can be very helpful in many scenarios:
#  when several administrators work together on the same server and need to know what was done previously
#  when someone need to redo an older sequence of commands or to understand an undocumented maintenance process
#  for troubleshooting or forensic analysis, by crosschecking the date of an event or of a file with the commands executed at that date
#
#The standard ‘.bash_history‘ file of the shell is unfortunately not written on disk in the case of a crash and it may be deleted by the user.
#Another problem is that when many shell sessions are running concurrently, their logging will only occur when they are closed, therefore the commands of the history will not appear in their chronological order.
#Furthermore, ‘.bash_history‘ will not include essential information like the ‘working directory‘ of the command; and by default the repetition or re-edition of commands will not be logged, too.
#
#Some solutions exist to improve this, either by patching or installing binaries:
#  ‘bash-BOFH‘ patching and recompiling: works well but need a new patch for each release of the bash
# ‘snoopy‘: is logging all commands except shell builtins
#  ‘rootsh / sniffy / ttyrpld / ttysnoop‘: logs everything, also output of commands, it may be useful but it generates very verbose logs
#  ‘grsecurity‘ patched kernels: powerful but it may be a not suitable solution if an official kernel is required (e.g. for Oracle DB)
#  there is also an old ‘sshd‘ patch (‘http://www.kdvelectronics.eu/ssh-logging/ssh-logging.html‘)
#  ‘screen -x‘ can also be useful for cooperation work, but it is not a command logger
#
#In contrast to that, the presented method is very easy to deploy; it is just a shellscript that is running in bash (standard shell on most systems) and therefore it is architecture independent.
#It will allow a complete audit of all commands/builtins executed interactively in the bash.
#Note that a user can avoid calling this file by starting a shell with options like ‘--norc‘; he also can unset or overwrite variables like ‘PROMPT_COMMAND‘.
#Therefore this script is useful for audit but an alternative solution with bash patching should be considered if the security requirements are the priority.
#
#Note on Solaris:
#       In Solaris please use ‘grep‘ without the ‘-q‘ option, like this:
#               if groups | grep root &>/dev/null
#       Please also remove the following line (chattr unsupported in Solaris:
#               chattr +a "$HISTFILE"
#       Then modify your /etc/syslog.conf to include this line:
#               user.info /var/adm/userlog.info
#       To assign ‘bash‘ as the login shell in Solaris: passwd -e /bin/bash .
#       Make sure that the audit-script is sourced (=included) correctly during the bash invocation.
#       If your bash version is too old, $HISTCONTROL will not allow you to log duplicated commands correctly.
#       svcadm restart system/system-log
#       svcadm disable ssh
#       svcadm enable ssh
if [ "${SHELL##*/}" != "bash" ]; then
  return
fi
#to avoid sourcing this file more than once
if [ -n "${OSTYPE##solaris*}" ]; then #following not working in solaris
  #do not source this file twice; also do not source it if we are in forcecommand.sh, source it later from "-bash-li"
  #if we would source it from forcecommand.sh, the environment would be lost after the call of ‘exec -l bash -li‘
  if [ "$AUDIT_INCLUDED" == "$$" ] || { [ -z "$SSH_ORIGINAL_COMMAND" ] && [ "$(cat /proc/$$/cmdline)" == ‘bash-c"/etc/forcecommand.sh"‘ ]; }; then
    return
  else
    declare -rx AUDIT_INCLUDED="$$"
  fi
fi
#prompt & color
#‘http://www.pixelbeat.org/docs/terminal_colours/#256‘
#‘http://www.frexx.de/xterm-256-notes/‘
_backnone="\e[00m"
_backblack="\e[40m"
_backblue="\e[44m"
_frontred_b="\e[01;31m"
_frontgreen_b="\e[01;32m"
_frontgrey_b="\e[01;37m"
_frontgrey="\e[00;37m"
_frontblue_b="\e[01;34m"
#PS1="\[${_backblue}${_frontgrey_b}\]\[email protected]\h:\[${_backblack}${_frontblue_b}\]\w\\$\[${_backnone}${_frontgrey_b}\] " #grey
PS1="\[${_backblue}${_frontgreen_b}\]\[email protected]\h:\[${_backblack}${_frontblue_b}\]\w\\$\[${_backnone}${_frontgreen_b}\] " #green
#PS1="\[${_backblue}${_frontred_b}\]\[email protected]\h:\[${_backblack}${_frontblue_b}\]\w\\$\[${_backnone}${_frontred_b}\] " #red
declare -rx PS1
#‘history‘ options
declare -rx HISTFILE="$HOME/.bash_history"
declare -rx HISTSIZE=500000                                 #nbr of cmds in memory
declare -rx HISTFILESIZE=500000                             #nbr of cmds on file
declare -rx HISTCONTROL=""                                  #does not ignore spaces or duplicates
declare -rx HISTIGNORE=""                                   #does not ignore patterns
declare -rx HISTCMD                                         #history line number
#following line is commented to avoid following issue: loading the history during the sourcing of this file (non-interactive bash) is also loading history lines that begin with ‘#‘, but then during the trap DEBUG calls it reloads the whole history without ‘#‘-lines and produces an double-length history.
#history -r                                                  #to reload history from file if a prior HISTSIZE has truncated it
#following 2 lines commented because ‘history -r‘ was still loading ‘#‘-lines
#shopt -s extglob                                            #enable extended pattern matching operators
#HISTIGNORE="*([ \t])#*"; history -r                         #reload history without commented lines; this force non-interactive bash to behave like interactive bash, without this AUDIT_HISTLINE will get a wrong initial value, leading then to a small issue where empty bash sessions are actually logging the last command of history
if [ -n "${OSTYPE##solaris*}" ]; then #following not working in solaris
  if groups | grep -q root; then
    declare -x TMOUT=43200                                    #timeout for root‘s sessions
    chattr +a "$HISTFILE"                                     #set append-only
  fi
fi
shopt -s histappend
shopt -s cmdhist
#history substitution ask for a confirmation
shopt -s histverify
#add timestamps in history - obsoleted with logger/syslog
#‘http://www.thegeekstuff.com/2008/08/15-examples-to-master-linux-command-line-history/#more-130‘
#declare -rx HISTTIMEFORMAT=‘%F %T ‘
#enable forward search (‘ctrl-s‘)
#‘http://ruslanspivak.com/2010/11/25/bash-history-incremental-search-forward/‘
if shopt -q login_shell && [ -t 0 ]; then
  stty -ixon
fi
#bash audit & traceability
#
#
#
declare -rx AUDIT_LOGINUSER="$(who -mu | awk ‘{print $1}‘)"
declare -rx AUDIT_LOGINPID="$(who -mu | awk ‘{print $6}‘)"
declare -rx AUDIT_USER="$USER"                              #defined by pam during su/sudo
declare -rx AUDIT_PID="$$"
declare -rx AUDIT_TTY="$(who -mu | awk ‘{print $2}‘)"
declare -rx AUDIT_SSH="$([ -n "$SSH_CONNECTION" ] && echo "$SSH_CONNECTION" | awk ‘{print $1":"$2"->"$3":"$4}‘)"
declare -rx AUDIT_STR="[audit $AUDIT_LOGINUSER/$AUDIT_LOGINPID as $AUDIT_USER/$AUDIT_PID on $AUDIT_TTY/$AUDIT_SSH]"
declare -x AUDIT_LASTHISTLINE=""                            #to avoid logging the same line twice
declare -rx AUDIT_SYSLOG="1"                                #to use a local syslogd
#
#
#
#the logging at each execution of command is performed with a trap DEBUG function
#and having set the required history options (HISTCONTROL, HISTIGNORE)
#and to disable the trap in functions, command substitutions or subshells.
#it turns out that this solution is simple and works well with piped commands, subshells, aborted commands with ‘ctrl-c‘, etc..
set +o functrace                                            #disable trap DEBUG inherited in functions, command substitutions or subshells, normally the default setting already
shopt -s extglob                                            #enable extended pattern matching operators
function AUDIT_DEBUG() {
  if [ -z "$AUDIT_LASTHISTLINE" ]; then                     #initialization
    local AUDIT_CMD="$(fc -l -1 -1)"                        #previous history command
    AUDIT_LASTHISTLINE="${AUDIT_CMD%%+([^ 0-9])*}"
  else
    AUDIT_LASTHISTLINE="$AUDIT_HISTLINE"
  fi
  local AUDIT_CMD="$(history 1)"                            #current history command
  AUDIT_HISTLINE="${AUDIT_CMD%%+([^ 0-9])*}"
  if [ "${AUDIT_HISTLINE:-0}" -ne "${AUDIT_LASTHISTLINE:-0}" ] || [ "${AUDIT_HISTLINE:-0}" -eq "1" ]; then  #avoid logging unexecuted commands after ‘ctrl-c‘, ‘empty+enter‘, or after ‘ctrl-d‘
    echo -ne "${_backnone}${_frontgrey}"                    #disable prompt colors for the command‘s output
    #remove in last history cmd its line number (if any) and send to syslog
    if [ -n "$AUDIT_SYSLOG" ]; then
      if ! logger -p user.info -t "$AUDIT_STR $PWD" "${AUDIT_CMD##*( )?(+([0-9])?(\*)+( ))}"; then
        echo error "$AUDIT_STR $PWD" "${AUDIT_CMD##*( )?(+([0-9])?(\*)+( ))}"
      fi
    else
      echo $( date +%F_%H:%M:%S ) "$AUDIT_STR $PWD" "${AUDIT_CMD##*( )?(+([0-9])?(\*)+( ))}" >>/var/log/userlog.info
    fi
    #echo "===cmd:$BASH_COMMAND/subshell:$BASH_SUBSHELL/fc:$(fc -l -1)/history:$(history 1)/histline:${AUDIT_CMD%%+([^ 0-9])*}/last_histline:${AUDIT_LASTHISTLINE}===" #for debugging
    return 0
  else
    return 1
  fi
}
#
#
#
#audit the session closing
function AUDIT_EXIT() {
  local AUDIT_STATUS="$?"
  if [ -n "$AUDIT_SYSLOG" ]; then
    logger -p user.info -t "$AUDIT_STR" "#=== session closed ==="
  else
    echo $( date +%F_%H:%M:%S ) "$AUDIT_STR" "#=== session closed ===" >>/var/log/userlog.info
  fi
  exit "$AUDIT_STATUS"
}
#
#
#
#make audit trap functions readonly; disable trap DEBUG inherited (normally the default setting already)
declare -frx +t AUDIT_DEBUG
declare -frx +t AUDIT_EXIT
#
#
#
#audit the session opening
if [ -n "$AUDIT_SYSLOG" ]; then
  logger -p user.info -t "$AUDIT_STR" "#=== session opened ===" #audit the session openning
else
  echo $( date +%F_%H:%M:%S ) "$AUDIT_STR" "#=== session opened ===" >>/var/log/userlog.info
fi
#
#
#
#when a bash command is executed it launches first the AUDIT_DEBUG(),
#then the trap DEBUG is disabled to avoid a useless rerun of AUDIT_DEBUG() during the execution of pipes-commands;
#at the end, when the prompt is displayed, re-enable the trap DEBUG
        #declare -rx PROMPT_COMMAND="AUDIT_DONE=; trap ‘AUDIT_DEBUG && AUDIT_DONE=1; trap DEBUG‘ DEBUG; [ -n \"\$AUDIT_DONE\" ] && echo ‘-----------------------------‘"
        #NOK: declare -rx PROMPT_COMMAND="echo "-----------------------------"; trap ‘AUDIT_DEBUG; trap DEBUG‘ DEBUG; echo ‘-----------------------------‘"
        #OK:  declare -rx PROMPT_COMMAND="echo "-----------------------------"; trap ‘AUDIT_DEBUG; trap DEBUG‘ DEBUG"
declare -rx PROMPT_COMMAND="[ -n \"\$AUDIT_DONE\" ] && echo ‘-----------------------------‘; AUDIT_DONE=; trap ‘AUDIT_DEBUG && AUDIT_DONE=1; trap DEBUG‘ DEBUG"
declare -rx BASH_COMMAND                                    #current command executed by user or a trap
declare -rx SHELLOPT                                        #shell options, like functrace
trap AUDIT_EXIT EXIT                                        #audit the session closing
#endof

2、修改配置文件的属主数组和权限

#chown root:root /etc/bash_franzi
#chmod 644 /etc/bash_franzi

3、在命令行运行以下命令,让文件在系统启动时自动加载

for i in /etc/profile /etc/skel/.bashrc /root/.bashrc /home/*/.bashrc; do
  if ! grep -q ". /etc/bash_franzi" "$i"; then
    echo "===updating $i==="
    echo "[ -f /etc/bash_franzi ] && . /etc/bash_franzi #added by francois scheurer" >>"$i"
  fi
done

4、运行以下命令,配置/etc/rsyslog.conf文件

cat >>/etc/rsyslog.conf <<"EOF"
#added by francois scheurer
$ActionFileDefaultTemplate RSYSLOG_FileFormat
#stop avahi if messages are dropped (cf. /var/log/messages with ‘net_ratelimit‘ or ‘imuxsock begins to drop‘)
#update-rc.d -f avahi-daemon remove && service avahi-daemon stop
#https://isc.sans.edu/diary/Are+you+losing+system+logging+information+%28and+don%27t+know+it%29%3F/15106
#$SystemLogRateLimitInterval 10 
#$SystemLogRateLimitBurst 500
$SystemLogRateLimitInterval 0
#endof
EOF

5、创建‘/etc/rsyslog.d/45-franzi.conf’配置文件

cat >/etc/rsyslog.d/45-franzi.conf <<"EOF"
#added by francois scheurer
# Filter duplicated messages
$RepeatedMsgReduction off
# Enable high precision timestamps
$ActionFileDefaultTemplate RSYSLOG_FileFormat
# Log bash audit generated log messages to file
if $syslogfacility-text == ‘user‘ and $syslogseverity-text == ‘info‘ and $syslogtag startswith ‘[audit‘ then /var/log/userlog.info
#then drop them
& ~
#‘http://content.hccfl.edu/pollock/aunix2/logging.htm‘
#‘http://www.rsyslog.com/doc/rsyslog_conf_filter.html‘
EOF

6、重启rsyslog服务

/etc/init.d/rsyslog restart

效果:命令审计的日志保存在/var/log/userlog.info文件中

[email protected]:~# tail /var/log/userlog.info
2016-08-26T11:02:37.909499+08:00 localhost [audit root/23038 as root/23038 on pts/3/172.16.100.57:51374->10.10.10.202:22] /opt/sonar/conf: service iptables status
2016-08-26T11:02:44.619996+08:00 localhost [audit root/23038 as root/23038 on pts/3/172.16.100.57:51374->10.10.10.202:22] /opt/sonar/conf: service iptables stop
2016-08-26T11:02:50.489505+08:00 localhost [audit root/23038 as root/23038 on pts/3/172.16.100.57:51374->10.10.10.202:22] /opt/sonar/conf: sestatus -v
2016-08-26T11:03:03.369423+08:00 localhost [audit root/23038 as root/23038 on pts/3/172.16.100.57:51374->10.10.10.202:22] /opt/sonar/conf: chkconfig --list iptables 
2016-08-26T11:03:27.191368+08:00 localhost [audit root/23038 as root/23038 on pts/3/172.16.100.57:51374->10.10.10.202:22] /opt/sonar/conf: service ip6tables stop
2016-08-26T11:03:41.546837+08:00 localhost [audit root/23038 as root/23038 on pts/3/172.16.100.57:51374->10.10.10.202:22] /opt/sonar/conf: chkconfig ip6tables off
2016-08-26T11:13:40.509537+08:00 localhost [audit root/23038 as root/23038 on pts/3/172.16.100.57:51374->10.10.10.202:22] /opt/sonar/conf: /etc/init.d/jenkins stop
2016-08-26T11:13:46.641555+08:00 localhost [audit root/23038 as root/23038 on pts/3/172.16.100.57:51374->10.10.10.202:22] /opt/sonar/conf: /etc/init.d/jenkins start
2016-08-26T11:13:56.839747+08:00 localhost [audit root/23038 as root/23038 on pts/3/172.16.100.57:51374->10.10.10.202:22] /opt/sonar/conf: ps -ef | grep jenkins
2016-08-26T11:28:36.159554+08:00 localhost [audit root/19576 as root/19576 on pts/2/172.16.100.216:57196->10.10.10.202:22] /root: tail /var/log/userlog.info
时间: 2024-10-10 00:38:48

服务器命令审计的相关文章

linux利用PROMPT_COMMAND实现命令审计

网上查了实现命令审计大概有以下几种: 查不到了,改天再补充 以下环境基于CentOS 6 # history时间格式 sed -i '/^HISTSIZE/a HISTTIMEFORMAT="%F %T "' /etc/profile # 命令审计 cat > /etc/profile.d/cmd_log.sh << 'EOF' readonly PROMPT_COMMAND='{ cmd=$(history 1 | { read a b c d; echo &quo

键值和服务器命令

十九.键值和服务器命令127.0.0.1:6379> keys *            #列出所有键值1) "key3"2) "seta"3) "hash1"4) "list1"5) "key2"6) "zset1"7) "mset2"8) "set2"9) "set1"10) "key1"11) &

manjaro 命令审计普通用户log格式不生效问题解决记录

最近在折腾manjaro xfce 版本,实现命令审计参考如下博客https://blog.51cto.com/13227377/2159238具体操作如下:在/etc/profile后面添加 #history export HISTSIZE=4096 DT=`date +"%Y-%m-%d"` export HISTFILE="/opt/history/${LOGNAME}_history.log" chmod 600 /opt/history/${LOGNAME

PHP在Linux下Apache环境中执行exec,system,passthru等服务器命令函数

若在服务器中使用php test.php运行exec,system,passthru等命令相关的脚本能成功运行,在web页面却没反应,则 查看下apache的error_log日志,一般是这几个函数 system() has been disabled for security reasons in /var/www/html/test.php on line 34 报错了. 看下php.ini中的disable_functions 有没有禁用了这些函数,删除禁用后保存. 重启下php和Apac

Redis学习第七课:键值命令和服务器命令

Redis键值相关命令                                                                                                                                   keys:返回满足给定pattern的所有key.(用法:keys pattern表达式) exists:确认一个key是否存在.(用法:exists key) del:删除一个key.(用法:del key) ex

Linux本地登录另一台Linux服务器命令

要从Linux下通过SSH登录另一台Linux服务器非常容易--前提是在远 程服务器上拥有一个用户账号.打开Shell终端,执行以下命令 ssh -l login_name hostname 把login_name替换成真实的用户账号,把hostname替换成服务器主机名(或者IP地址).下面这条命令以liu 用户的身份登录到IP地址为192.168.25.99的Linux服务器上. [[email protected] ~]# ssh -l root 192.168.25.99[email p

日常使用服务器命令(centos)

1.用于显示磁盘分区上的可使用的磁盘空间.默认显示单位为KB.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息.常用命令如下:可读性较高的方式来显示信息: df -h 2.用来显示目标列表,在Linux中是使用率较高的命令.ls命令的输出信息可以进行彩色加亮显示,以分区不同类型的文件.常用命令如下:列出可读文件和文件夹详细信息 ls -lh 3.根据PID查询是那个应用 ll /proc/PID //cmd后为运行程序 4.两个服务器之间拷贝文件 //拷贝单个文件命令: scp

Redis 笔记与总结5 Redis 常用命令之 键值命令 和 服务器命令 &amp;&amp; 高级应用之 安全性 和 主从复制

Redis 提供了丰富的命令对数据库和各种数据库类型进行操作,这些命令可以在 Linux 终端使用. 1. 键值相关命令: 2. 服务器相关命令 键值相关命令 ① keys 命令 返回满足给定 pattern 的所有 key. [例] 127.0.0.1:6379> keys * 1) "time" 2) "list4" 3) "list1" 4) "email" 5) "age" 6) "

debian访问ftp服务器命令

在linux访问时输入 用户名 anonymous 密码直接回车可以匿名登录 连接ftp服务器 格式:ftp [hostname| ip-address] a)在linux命令行下输入:ftp 10.18.34.115 b)服务器询问你用户名和口令,分别输入yint和相应密码,待认证通过即可. 2. 下载文件 下载文件通常用get和mget这两条命令. a) get 格式:get [remote-file] [local-file] 将文件从远端主机中传送至本地主机中. 如要获取服务器上E:\r