前段时间需要对服务器的所有shell操作做一个审计,上网查了查大概有这么几种实现方式:

  1. 修改环境变量“PROMPT_COMMAND”
  2. 给bash打补丁‘bash-BOFH’
  3. shell封装‘rootsh / sniffy / ttyrpld / ttysnoop’

修改“PROMPT_COMMAND”最为简单快捷,问题在于使用history命令只能在执行结束以后才能得到审计结果,效果不好还可能丢失审计日志;打补丁维护比较麻烦,如果bash升级需要重新打补丁编译;而几个shell封装的程序打印出太多的日志,和需求不符合。后来查到了一种相对简单(shell脚本实现)又符合需求的方法,参考连接:http://www.pointsoftware.ch/de/howto-bash-audit-command-logger/。

这个方法的原理是通过shell的trap命令在shell命令执行前指定自定义的函数。trap是一个shell内建命令,它用来在脚本中指定信号如何处理。比如,按Ctrl+C会使脚本终止执行,实际上系统发送了SIGINT信号给脚本进程,SIGINT信号的默认处理方式就是退出程序。如果要在Ctrl+C不退出程序,那么就得使用trap命令来指定一下SIGINT的处理方式了。trap命令不仅仅处理Linux信号,还能对脚本退出(EXIT)、调试(DEBUG)、错误(ERR)、返回(RETURN)等情况指定处理方式。这里选用DEBUG来插入审计函数,具体实现参考下面的脚本:

#! /bin/bashcat >> /etc/bash_audit <<"EOF"
#to avoid sourcing this file more than once
if [ "${OSTYPE:0:7}" != "solaris" ] #following not working in solaris
then#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"' ]; }
thenreturn
elsedeclare -rx AUDIT_INCLUDED="$$"
fi
fi#prompt & color
_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}\]\u@\h:\[${_backblack}${_frontblue_b}\]\w\\$\[${_backnone}${_frontgrey_b}\] " #grey
PS1="\[${_backblue}${_frontgreen_b}\]\u@\h:\[${_backblack}${_frontblue_b}\]\w\\$\[${_backnone}${_frontgreen_b}\] " #green
#PS1="\[${_backblue}${_frontred_b}\]\u@\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 historyif [ "${OSTYPE:0:7}" != "solaris" ] #following not working in solaris
then
if groups | grep -q root
thendeclare -x TMOUT=3600                                     #timeout for root's sessionschattr +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 ]
thenstty -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" ]                           #initializationthenlocal AUDIT_CMD="$(fc -l -1 -1)"                        #previous history commandAUDIT_LASTHISTLINE="${AUDIT_CMD%%+([^ 0-9])*}"elseAUDIT_LASTHISTLINE="$AUDIT_HISTLINE"filocal AUDIT_CMD="$(history 1)"                            #current history commandAUDIT_HISTLINE="${AUDIT_CMD%%+([^ 0-9])*}"if [ "${AUDIT_HISTLINE:-0}" -ne "${AUDIT_LASTHISTLINE:-0}" ] || [ "${AUDIT_HISTLINE:-0}" -eq "1" ]        #avoid logging unexecuted commands after 'ctrl-c', 'empty+enter', or after 'ctrl-d'thenecho -ne "${_backnone}${_frontgrey}"                    #disable prompt colors for the command's output#remove in last history cmd its line number (if any) and send to syslogif [ -n "$AUDIT_SYSLOG" ]thenif ! logger -p user.info -t "$AUDIT_STR $PWD" "${AUDIT_CMD##*( )?(+([0-9])?(\*)+( ))}"thenecho error "$AUDIT_STR $PWD" "${AUDIT_CMD##*( )?(+([0-9])?(\*)+( ))}"fielseecho $( date +%F_%H:%M:%S ) "$AUDIT_STR $PWD" "${AUDIT_CMD##*( )?(+([0-9])?(\*)+( ))}" >>/var/log/userlog.infofi#echo "===cmd:$BASH_COMMAND/subshell:$BASH_SUBSHELL/fc:$(fc -l -1)/history:$(history 1)/histline:${AUDIT_CMD%%+([^ 0-9])*}/last_histline:${AUDIT_LASTHISTLINE}===" #for debuggingreturn 0elsereturn 1fi
}
#
#
#
#audit the session closing
function AUDIT_EXIT() {local AUDIT_STATUS="$?"if [ -n "$AUDIT_SYSLOG" ]thenlogger -p user.info -t "$AUDIT_STR" "#=== session closed ==="elseecho $( date +%F_%H:%M:%S ) "$AUDIT_STR" "#=== session closed ===" >>/var/log/userlog.infofiexit "$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" ]
thenlogger -p user.info -t "$AUDIT_STR" "#=== session opened ===" #audit the session openning
elseecho $( 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
EOFchown root:root /etc/bash_audit
chmod 644 /etc/bash_auditfor i in /etc/profile /etc/skel/.bashrc /root/.bashrc /home/*/.bashrc; doif ! grep -q ". /etc/bash_audit" "$i"thenecho "===updating $i==="echo "[ -f /etc/bash_audit ] && . /etc/bash_audit #added by franzi" >>"$i"fi
donecat >>/etc/rsyslog.conf <<"EOF"
#added by franzi
$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
#$SystemLogRateLimitInterval 10
#$SystemLogRateLimitBurst 500
$SystemLogRateLimitInterval 0
#endof
EOFcat >/etc/rsyslog.d/45-xsserver.conf <<"EOF"
#added by franzi# 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
& ~EOF

简单实现linux shell命令审计相关推荐

  1. linux help命令编写,Linux shell命令帮助格式详解

    前言 linux shell命令通常可以通过-h或--help来打印帮助说明,或者通过man命令来查看帮助,有时候我们也会给自己的程序写简单的帮助说明,其实帮助说明格式是有规律可循的 帮助示例 下面是 ...

  2. 最牛B 的 Linux Shell 命令

    最牛B 的 Linux Shell 命令(一) 引言 Shell作为Unix系操作系统当中最有魅力且不可或缺的组件,经过数十载的洗礼不仅没有被淘汰,而且愈加变得成熟稳健,究其原因,大概因为它是个非常稳 ...

  3. 常用的高级Linux shell命令

    编者按本文编译自commandlinefu.com的系列文章To p Ten One-Liners from CommandLineFu Explained.作为一个由用户推荐最有用shell命令的网 ...

  4. 最牛B的Linux Shell命令 系列

    编者按 本文编译自commandlinefu.com的系列文章Top Ten One-Liners from CommandLineFu Explained.作为一个由用户推荐最有用shell命令的网 ...

  5. Linux shell命令总结

    01 前言 Linux shell命令应该算是非常入门的东西,但是实际上在使用的时候,会遇到各种各样的问题,前几天我在我们的项目上需要做一个功能,根据进程名字杀死这个进程,下面是过程 1.我们正常需要 ...

  6. 8则实用的Linux Shell命令

    8则实用的Linux Shell命令 1 为 man 手册创建 pdf 版本 man -t manpage | ps2pdf - filename.pdf 比如制作 ls 命令的 man 手册 pdf ...

  7. 37条常用Linux Shell命令组合

    2019独角兽企业重金招聘Python工程师标准>>> 37条常用Linux Shell命令组合,推荐个各位网友,老手和新手们都值得收集和总结的东西.一起来看看 序号 任务 命令组合 ...

  8. Linux Shell命令能力倾向问题和解答

    This section contains Aptitude Questions and Answers on Linux Shell Commands. 本节包含有关Linux Shell命令的 A ...

  9. python commands执行不连续_[Python] 利用commands模块执行Linux shell命令

    用Python写运维脚本时,经常需要执行linux shell的命令,Python中的commands模块专门用于调用Linux shell命令,并返回状态和结果,下面是commands模块的3个主要 ...

最新文章

  1. plsql导入到mysql数据库乱码问题_PLSQL打开sql文件中文乱码解决方案
  2. python快速入门 pdf-Python快速入门 (第3版) PDF 下载
  3. leetcode-169.求众数
  4. GDCM:gdcm::Defs的测试程序
  5. WinCE中命令行工具Viewbin简介
  6. Java设计模式(2 / 23):观察者模式
  7. 奢华还是土嗨?8848新品钛金手机将于3月29日开启预售
  8. 【转】一个基于Ajax的通用(组合)查询(ASP.NET)
  9. mysql queries 很大,mysql优化通常使用的几种方法
  10. 如何将手机中Word文档转换成PDF
  11. 11.11如何卖到一个亿:从0到1的电商爆品打造术 电子书 PDF
  12. 学设计的考PMP证书有用吗?
  13. 华为+android+root权限获取root,[Android]如何获取华为手机的root权限
  14. 2010年下半年卷烟品牌目录
  15. 支付宝积分兑换的扫地机器人好用_如何选购扫地机器人?
  16. AcWing 342. 道路与航线 (双端队列广搜问题,SPFA)
  17. android 系统中的时区设置
  18. 碧水风荷录-第一章(未完,正在整理中……)
  19. JavaScript中的拖拽事件且限制出界
  20. Windows Server 2012 NIC Teaming 网卡绑定介绍及注意事项

热门文章

  1. 怎么借助Camtasia给电脑游戏录屏
  2. CKEditor5 支持 WPS 贴贴文字图片,默认贴贴进入空白空格
  3. iOS系统手机备忘录推荐
  4. coreldraw矫正两张图_coreldraw软件怎样图像倾斜矫正?
  5. PADS Laout栅格设置推荐
  6. 小论文双栏插入脚注(脚注也为双栏)
  7. npm 编译报错extract:echarts:sillextract echarts@^4.2.0-rc.2 extracted to
  8. 大数据——数据量级单位汇总
  9. mysql单表存放上亿数据,查询依旧很快。
  10. 鸿蒙和中兴新支点系统,鸿蒙和中兴新支点操作系统共同打造国产操作系统生态圈...