博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
服务器命令审计
阅读量:7177 次
发布时间:2019-06-29

本文共 14681 字,大约阅读时间需要 48 分钟。

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

下面是命令审计的方法:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#!/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}\]\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 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、修改配置文件的属主数组和权限

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

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

1
2
3
4
5
6
for 
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文件

1
2
3
4
5
6
7
8
9
10
11
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’配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
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文件中

1
2
3
4
5
6
7
8
9
10
11
root@localhost:~
# 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
本文转自 曾哥最爱 51CTO博客,原文链接:http://blog.51cto.com/zengestudy/1842879,如需转载请自行联系原作者
你可能感兴趣的文章
LAMP架构讲解(续一)
查看>>
51la图片做网店流量统计
查看>>
压力测试工具JMeter入门教程
查看>>
MySQL 百万级分页优化 数据库优化
查看>>
np.concatenate 拼接
查看>>
PHP编译错误解决:Don't know how to define struct flock on this system, set --enable-opcache=no...
查看>>
Linux命令(6):more命令
查看>>
HTTPD配置文件MPM(非7.0以上版本)
查看>>
Upgrade GI/CRS 11.1.0.7 to 11.2.0.2. Rootupgrade.sh Hanging
查看>>
nginx的高级配置(5)——访问控制
查看>>
DG_Oracle DataGuard Switchover主备节点切换(案例)
查看>>
CentOS7系统常用命令
查看>>
10.2.0.1 db console启动失败问题一例
查看>>
linux下查看文件编码及修改编码
查看>>
VC中的延时
查看>>
算法与数据结构知识点
查看>>
在单位成功实验的PIX配置
查看>>
centos6.x使用dd命令制作u盘启动
查看>>
如何使用Wireshark抓包
查看>>
mysql 时间函数用法 集合
查看>>