天天看點

伺服器指令審計

生産伺服器通常多個使用者具有登入權限和操作權限。那麼我們怎麼需要知道這些使用者登入伺服器後做了哪些操作?這就需要做指令審計,即統計登入使用者在伺服器上執行了哪些指令。

下面是指令審計的方法:

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

<code>#!/usr/bin/env bash</code>

<code>#Pointsoftware AG, 2013-11-03</code>

<code>#created by francois scheurer</code>

<code>#filename: '/etc/bash_franzi'</code>

<code>#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.</code>

<code>#</code>

<code>#Having a complete history of all typed commands can be very helpful in many scenarios:</code>

<code>#  when several administrators work together on the same server and need to know what was done previously</code>

<code>#  when someone need to redo an older sequence of commands or to understand an undocumented maintenance process</code>

<code>#  for troubleshooting or forensic analysis, by crosschecking the date of an event or of a file with the commands executed at that date</code>

<code>#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.</code>

<code>#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.</code>

<code>#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.</code>

<code>#Some solutions exist to improve this, either by patching or installing binaries:</code>

<code>#  'bash-BOFH' patching and recompiling: works well but need a new patch for each release of the bash</code>

<code># 'snoopy': is logging all commands except shell builtins</code>

<code>#  'rootsh / sniffy / ttyrpld / ttysnoop': logs everything, also output of commands, it may be useful but it generates very verbose logs</code>

<code>#  'grsecurity' patched kernels: powerful but it may be a not suitable solution if an official kernel is required (e.g. for Oracle DB)</code>

<code>#  there is also an old 'sshd' patch ('http://www.kdvelectronics.eu/ssh-logging/ssh-logging.html')</code>

<code>#  'screen -x' can also be useful for cooperation work, but it is not a command logger</code>

<code>#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.</code>

<code>#It will allow a complete audit of all commands/builtins executed interactively in the bash.</code>

<code>#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'.</code>

<code>#Therefore this script is useful for audit but an alternative solution with bash patching should be considered if the security requirements are the priority.</code>

<code>#Note on Solaris:</code>

<code>#       In Solaris please use 'grep' without the '-q' option, like this:</code>

<code>#               if groups | grep root &amp;&gt;/dev/null</code>

<code>#       Please also remove the following line (chattr unsupported in Solaris:</code>

<code>#               chattr +a "$HISTFILE"</code>

<code>#       Then modify your /etc/syslog.conf to include this line:</code>

<code>#               user.info /var/adm/userlog.info</code>

<code>#       To assign 'bash' as the login shell in Solaris: passwd -e /bin/bash .</code>

<code>#       Make sure that the audit-script is sourced (=included) correctly during the bash invocation.</code>

<code>#       If your bash version is too old, $HISTCONTROL will not allow you to log duplicated commands correctly.</code>

<code>#       svcadm restart system/system-log</code>

<code>#       svcadm disable ssh</code>

<code>#       svcadm enable ssh</code>

<code>if</code> <code>[ </code><code>"${SHELL##*/}"</code> <code>!= </code><code>"bash"</code> <code>]; </code><code>then</code>

<code>  </code><code>return</code>

<code>fi</code>

<code>#to avoid sourcing this file more than once</code>

<code>if</code> <code>[ -n </code><code>"${OSTYPE##solaris*}"</code> <code>]; </code><code>then</code> <code>#following not working </code><code>in</code> <code>solaris</code>

<code>  </code><code>#do not source this file twice; also do not source it if we are in forcecommand.sh, source it later from "-bash-li"</code>

<code>  </code><code>#if we would source it from forcecommand.sh, the environment would be lost after the call of 'exec -l bash -li'</code>

<code>  </code><code>if</code> <code>[ </code><code>"$AUDIT_INCLUDED"</code> <code>== </code><code>"$$"</code> <code>] || { [ -z </code><code>"$SSH_ORIGINAL_COMMAND"</code> <code>] &amp;&amp; [ </code><code>"$(cat /proc/$$/cmdline)"</code> <code>== </code><code>'bash-c"/etc/forcecommand.sh"'</code> <code>]; }; </code><code>then</code>

<code>    </code><code>return</code>

<code>  </code><code>else</code>

<code>    </code><code>declare</code> <code>-rx AUDIT_INCLUDED=</code><code>"$$"</code>

<code>  </code><code>fi</code>

<code>#prompt &amp; color</code>

<code>#'http://www.pixelbeat.org/docs/terminal_colours/#256'</code>

<code>#'http://www.frexx.de/xterm-256-notes/'</code>

<code>_backnone=</code><code>"\e[00m"</code>

<code>_backblack=</code><code>"\e[40m"</code>

<code>_backblue=</code><code>"\e[44m"</code>

<code>_frontred_b=</code><code>"\e[01;31m"</code>

<code>_frontgreen_b=</code><code>"\e[01;32m"</code>

<code>_frontgrey_b=</code><code>"\e[01;37m"</code>

<code>_frontgrey=</code><code>"\e[00;37m"</code>

<code>_frontblue_b=</code><code>"\e[01;34m"</code>

<code>#PS1="\[${_backblue}${_frontgrey_b}\]\u@\h:\[${_backblack}${_frontblue_b}\]\w\\$\[${_backnone}${_frontgrey_b}\] " #grey</code>

<code>PS1=</code><code>"\[${_backblue}${_frontgreen_b}\]\u@\h:\[${_backblack}${_frontblue_b}\]\w\\$\[${_backnone}${_frontgreen_b}\] "</code> <code>#green</code>

<code>#PS1="\[${_backblue}${_frontred_b}\]\u@\h:\[${_backblack}${_frontblue_b}\]\w\\$\[${_backnone}${_frontred_b}\] " #red</code>

<code>declare</code> <code>-rx PS1</code>

<code>#'history' options</code>

<code>declare</code> <code>-rx HISTFILE=</code><code>"$HOME/.bash_history"</code>

<code>declare</code> <code>-rx HISTSIZE=500000                                 </code><code>#nbr of cmds in memory</code>

<code>declare</code> <code>-rx HISTFILESIZE=500000                             </code><code>#nbr of cmds on file</code>

<code>declare</code> <code>-rx HISTCONTROL=</code><code>""</code>                                  <code>#does not ignore spaces or duplicates</code>

<code>declare</code> <code>-rx HISTIGNORE=</code><code>""</code>                                   <code>#does not ignore patterns</code>

<code>declare</code> <code>-rx HISTCMD                                         </code><code>#history line number</code>

<code>#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.</code>

<code>#history -r                                                  #to reload history from file if a prior HISTSIZE has truncated it</code>

<code>#following 2 lines commented because 'history -r' was still loading '#'-lines</code>

<code>#shopt -s extglob                                            #enable extended pattern matching operators</code>

<code>#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</code>

<code>  </code><code>if</code> <code>groups</code> <code>| </code><code>grep</code> <code>-q root; </code><code>then</code>

<code>    </code><code>declare</code> <code>-x TMOUT=43200                                    </code><code>#timeout for root's sessions</code>

<code>    </code><code>chattr +a </code><code>"$HISTFILE"</code>                                     <code>#set append-only</code>

<code>shopt</code> <code>-s histappend</code>

<code>shopt</code> <code>-s cmdhist</code>

<code>#history substitution ask for a confirmation</code>

<code>shopt</code> <code>-s histverify</code>

<code>#add timestamps in history - obsoleted with logger/syslog</code>

<code>#'http://www.thegeekstuff.com/2008/08/15-examples-to-master-linux-command-line-history/#more-130'</code>

<code>#declare -rx HISTTIMEFORMAT='%F %T '</code>

<code>#enable forward search ('ctrl-s')</code>

<code>#'http://ruslanspivak.com/2010/11/25/bash-history-incremental-search-forward/'</code>

<code>if</code> <code>shopt</code> <code>-q login_shell &amp;&amp; [ -t 0 ]; </code><code>then</code>

<code>  </code><code>stty -ixon</code>

<code>#bash audit &amp; traceability</code>

<code>declare</code> <code>-rx AUDIT_LOGINUSER=</code><code>"$(who -mu | awk '{print $1}')"</code>

<code>declare</code> <code>-rx AUDIT_LOGINPID=</code><code>"$(who -mu | awk '{print $6}')"</code>

<code>declare</code> <code>-rx AUDIT_USER=</code><code>"$USER"</code>                              <code>#defined by pam during su/sudo</code>

<code>declare</code> <code>-rx AUDIT_PID=</code><code>"$$"</code>

<code>declare</code> <code>-rx AUDIT_TTY=</code><code>"$(who -mu | awk '{print $2}')"</code>

<code>declare</code> <code>-rx AUDIT_SSH=</code><code>"$([ -n "</code><code>$SSH_CONNECTION</code><code>" ] &amp;&amp; echo "</code><code>$SSH_CONNECTION</code><code>" | awk '{print $1"</code><code>:</code><code>"$2"</code><code>-&gt;</code><code>"$3"</code><code>:</code><code>"$4}')"</code>

<code>declare</code> <code>-rx AUDIT_STR=</code><code>"[audit $AUDIT_LOGINUSER/$AUDIT_LOGINPID as $AUDIT_USER/$AUDIT_PID on $AUDIT_TTY/$AUDIT_SSH]"</code>

<code>declare</code> <code>-x AUDIT_LASTHISTLINE=</code><code>""</code>                            <code>#to avoid logging the same line twice</code>

<code>declare</code> <code>-rx AUDIT_SYSLOG=</code><code>"1"</code>                                <code>#to use a local syslogd</code>

<code>#the logging at each execution of command is performed with a trap DEBUG function</code>

<code>#and having set the required history options (HISTCONTROL, HISTIGNORE)</code>

<code>#and to disable the trap in functions, command substitutions or subshells.</code>

<code>#it turns out that this solution is simple and works well with piped commands, subshells, aborted commands with 'ctrl-c', etc..</code>

<code>set</code> <code>+o functrace                                            </code><code>#disable trap DEBUG inherited in functions, command substitutions or subshells, normally the default setting already</code>

<code>shopt</code> <code>-s extglob                                            </code><code>#enable extended pattern matching operators</code>

<code>function</code> <code>AUDIT_DEBUG() {</code>

<code>  </code><code>if</code> <code>[ -z </code><code>"$AUDIT_LASTHISTLINE"</code> <code>]; </code><code>then</code>                     <code>#initialization</code>

<code>    </code><code>local</code> <code>AUDIT_CMD=</code><code>"$(fc -l -1 -1)"</code>                        <code>#previous history command</code>

<code>    </code><code>AUDIT_LASTHISTLINE=</code><code>"${AUDIT_CMD%%+([^ 0-9])*}"</code>

<code>    </code><code>AUDIT_LASTHISTLINE=</code><code>"$AUDIT_HISTLINE"</code>

<code>  </code><code>local</code> <code>AUDIT_CMD=</code><code>"$(history 1)"</code>                            <code>#current history command</code>

<code>  </code><code>AUDIT_HISTLINE=</code><code>"${AUDIT_CMD%%+([^ 0-9])*}"</code>

<code>  </code><code>if</code> <code>[ </code><code>"${AUDIT_HISTLINE:-0}"</code> <code>-</code><code>ne</code> <code>"${AUDIT_LASTHISTLINE:-0}"</code> <code>] || [ </code><code>"${AUDIT_HISTLINE:-0}"</code> <code>-</code><code>eq</code> <code>"1"</code> <code>]; </code><code>then</code>  <code>#avoid logging unexecuted commands after 'ctrl-c', 'empty+enter', or after 'ctrl-d'</code>

<code>    </code><code>echo</code> <code>-</code><code>ne</code> <code>"${_backnone}${_frontgrey}"</code>                    <code>#disable prompt colors for the command's output</code>

<code>    </code><code>#remove in last history cmd its line number (if any) and send to syslog</code>

<code>    </code><code>if</code> <code>[ -n </code><code>"$AUDIT_SYSLOG"</code> <code>]; </code><code>then</code>

<code>      </code><code>if</code> <code>! logger -p user.info -t </code><code>"$AUDIT_STR $PWD"</code> <code>"${AUDIT_CMD##*( )?(+([0-9])?(\*)+( ))}"</code><code>; </code><code>then</code>

<code>        </code><code>echo</code> <code>error </code><code>"$AUDIT_STR $PWD"</code> <code>"${AUDIT_CMD##*( )?(+([0-9])?(\*)+( ))}"</code>

<code>      </code><code>fi</code>

<code>    </code><code>else</code>

<code>      </code><code>echo</code> <code>$( </code><code>date</code> <code>+%F_%H:%M:%S ) </code><code>"$AUDIT_STR $PWD"</code> <code>"${AUDIT_CMD##*( )?(+([0-9])?(\*)+( ))}"</code> <code>&gt;&gt;</code><code>/var/log/userlog</code><code>.info</code>

<code>    </code><code>fi</code>

<code>    </code><code>#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</code>

<code>    </code><code>return</code> <code>0</code>

<code>    </code><code>return</code> <code>1</code>

<code>}</code>

<code>#audit the session closing</code>

<code>function</code> <code>AUDIT_EXIT() {</code>

<code>  </code><code>local</code> <code>AUDIT_STATUS=</code><code>"$?"</code>

<code>  </code><code>if</code> <code>[ -n </code><code>"$AUDIT_SYSLOG"</code> <code>]; </code><code>then</code>

<code>    </code><code>logger -p user.info -t </code><code>"$AUDIT_STR"</code> <code>"#=== session closed ==="</code>

<code>    </code><code>echo</code> <code>$( </code><code>date</code> <code>+%F_%H:%M:%S ) </code><code>"$AUDIT_STR"</code> <code>"#=== session closed ==="</code> <code>&gt;&gt;</code><code>/var/log/userlog</code><code>.info</code>

<code>  </code><code>exit</code> <code>"$AUDIT_STATUS"</code>

<code>#make audit trap functions readonly; disable trap DEBUG inherited (normally the default setting already)</code>

<code>declare</code> <code>-frx +t AUDIT_DEBUG</code>

<code>declare</code> <code>-frx +t AUDIT_EXIT</code>

<code>#audit the session opening</code>

<code>if</code> <code>[ -n </code><code>"$AUDIT_SYSLOG"</code> <code>]; </code><code>then</code>

<code>  </code><code>logger -p user.info -t </code><code>"$AUDIT_STR"</code> <code>"#=== session opened ==="</code> <code>#audit the session openning</code>

<code>else</code>

<code>  </code><code>echo</code> <code>$( </code><code>date</code> <code>+%F_%H:%M:%S ) </code><code>"$AUDIT_STR"</code> <code>"#=== session opened ==="</code> <code>&gt;&gt;</code><code>/var/log/userlog</code><code>.info</code>

<code>#when a bash command is executed it launches first the AUDIT_DEBUG(),</code>

<code>#then the trap DEBUG is disabled to avoid a useless rerun of AUDIT_DEBUG() during the execution of pipes-commands;</code>

<code>#at the end, when the prompt is displayed, re-enable the trap DEBUG</code>

<code>        </code><code>#declare -rx PROMPT_COMMAND="AUDIT_DONE=; trap 'AUDIT_DEBUG &amp;&amp; AUDIT_DONE=1; trap DEBUG' DEBUG; [ -n \"\$AUDIT_DONE\" ] &amp;&amp; echo '-----------------------------'"</code>

<code>        </code><code>#NOK: declare -rx PROMPT_COMMAND="echo "-----------------------------"; trap 'AUDIT_DEBUG; trap DEBUG' DEBUG; echo '-----------------------------'"</code>

<code>        </code><code>#OK:  declare -rx PROMPT_COMMAND="echo "-----------------------------"; trap 'AUDIT_DEBUG; trap DEBUG' DEBUG"</code>

<code>declare</code> <code>-rx PROMPT_COMMAND=</code><code>"[ -n \"\$AUDIT_DONE\" ] &amp;&amp; echo '-----------------------------'; AUDIT_DONE=; trap 'AUDIT_DEBUG &amp;&amp; AUDIT_DONE=1; trap DEBUG' DEBUG"</code>

<code>declare</code> <code>-rx BASH_COMMAND                                    </code><code>#current command executed by user or a trap</code>

<code>declare</code> <code>-rx SHELLOPT                                        </code><code>#shell options, like functrace</code>

<code>trap</code> <code>AUDIT_EXIT EXIT                                        </code><code>#audit the session closing</code>

<code>#endof</code>

2、修改配置檔案的屬主數組和權限

<code>#chown root:root /etc/bash_franzi</code>

<code>#chmod 644 /etc/bash_franzi</code>

3、在指令行運作以下指令,讓檔案在系統啟動時自動加載

<code>for</code> <code>i </code><code>in</code> <code>/etc/profile</code> <code>/etc/skel/</code><code>.bashrc </code><code>/root/</code><code>.bashrc </code><code>/home/</code><code>*/.bashrc; </code><code>do</code>

<code>  </code><code>if</code> <code>! </code><code>grep</code> <code>-q </code><code>". /etc/bash_franzi"</code> <code>"$i"</code><code>; </code><code>then</code>

<code>    </code><code>echo</code> <code>"===updating $i==="</code>

<code>    </code><code>echo</code> <code>"[ -f /etc/bash_franzi ] &amp;&amp; . /etc/bash_franzi #added by francois scheurer"</code> <code>&gt;&gt;</code><code>"$i"</code>

<code>done</code>

4、運作以下指令,配置/etc/rsyslog.conf檔案

<code>cat</code> <code>&gt;&gt;</code><code>/etc/rsyslog</code><code>.conf &lt;&lt;</code><code>"EOF"</code>

<code>#added by francois scheurer</code>

<code>$ActionFileDefaultTemplate RSYSLOG_FileFormat</code>

<code>#stop avahi if messages are dropped (cf. /var/log/messages with 'net_ratelimit' or 'imuxsock begins to drop')</code>

<code>#update-rc.d -f avahi-daemon remove &amp;&amp; service avahi-daemon stop</code>

<code>#https://isc.sans.edu/diary/Are+you+losing+system+logging+information+%28and+don%27t+know+it%29%3F/15106</code>

<code>#$SystemLogRateLimitInterval 10 </code>

<code>#$SystemLogRateLimitBurst 500</code>

<code>$SystemLogRateLimitInterval 0</code>

<code>EOF</code>

5、建立‘/etc/rsyslog.d/45-franzi.conf’配置檔案

<code>cat</code> <code>&gt;</code><code>/etc/rsyslog</code><code>.d</code><code>/45-franzi</code><code>.conf &lt;&lt;</code><code>"EOF"</code>

<code># Filter duplicated messages</code>

<code>$RepeatedMsgReduction off</code>

<code># Enable high precision timestamps</code>

<code># Log bash audit generated log messages to file</code>

<code>if</code> <code>$syslogfacility-text == </code><code>'user'</code> <code>and $syslogseverity-text == </code><code>'info'</code> <code>and $syslogtag startswith </code><code>'[audit'</code> <code>then</code> <code>/var/log/userlog</code><code>.info</code>

<code>#then drop them</code>

<code>&amp; ~</code>

<code>#'http://content.hccfl.edu/pollock/aunix2/logging.htm'</code>

<code>#'http://www.rsyslog.com/doc/rsyslog_conf_filter.html'</code>

6、重新開機rsyslog服務

/etc/init.d/rsyslog restart

效果:指令審計的日志儲存在/var/log/userlog.info檔案中

<code>root@localhost:~</code><code># tail /var/log/userlog.info</code>

<code>2016-08-26T11:02:37.909499+08:00 localhost [audit root</code><code>/23038</code> <code>as root</code><code>/23038</code> <code>on pts</code><code>/3/172</code><code>.16.100.57:51374-&gt;10.10.10.202:22] </code><code>/opt/sonar/conf</code><code>: service iptables status</code>

<code>2016-08-26T11:02:44.619996+08:00 localhost [audit root</code><code>/23038</code> <code>as root</code><code>/23038</code> <code>on pts</code><code>/3/172</code><code>.16.100.57:51374-&gt;10.10.10.202:22] </code><code>/opt/sonar/conf</code><code>: service iptables stop</code>

<code>2016-08-26T11:02:50.489505+08:00 localhost [audit root</code><code>/23038</code> <code>as root</code><code>/23038</code> <code>on pts</code><code>/3/172</code><code>.16.100.57:51374-&gt;10.10.10.202:22] </code><code>/opt/sonar/conf</code><code>: sestatus -</code><code>v</code>

<code>2016-08-26T11:03:03.369423+08:00 localhost [audit root</code><code>/23038</code> <code>as root</code><code>/23038</code> <code>on pts</code><code>/3/172</code><code>.16.100.57:51374-&gt;10.10.10.202:22] </code><code>/opt/sonar/conf</code><code>: chkconfig --list iptables </code>

<code>2016-08-26T11:03:27.191368+08:00 localhost [audit root</code><code>/23038</code> <code>as root</code><code>/23038</code> <code>on pts</code><code>/3/172</code><code>.16.100.57:51374-&gt;10.10.10.202:22] </code><code>/opt/sonar/conf</code><code>: service ip6tables stop</code>

<code>2016-08-26T11:03:41.546837+08:00 localhost [audit root</code><code>/23038</code> <code>as root</code><code>/23038</code> <code>on pts</code><code>/3/172</code><code>.16.100.57:51374-&gt;10.10.10.202:22] </code><code>/opt/sonar/conf</code><code>: chkconfig ip6tables off</code>

<code>2016-08-26T11:13:40.509537+08:00 localhost [audit root</code><code>/23038</code> <code>as root</code><code>/23038</code> <code>on pts</code><code>/3/172</code><code>.16.100.57:51374-&gt;10.10.10.202:22] </code><code>/opt/sonar/conf</code><code>: </code><code>/etc/init</code><code>.d</code><code>/jenkins</code> <code>stop</code>

<code>2016-08-26T11:13:46.641555+08:00 localhost [audit root</code><code>/23038</code> <code>as root</code><code>/23038</code> <code>on pts</code><code>/3/172</code><code>.16.100.57:51374-&gt;10.10.10.202:22] </code><code>/opt/sonar/conf</code><code>: </code><code>/etc/init</code><code>.d</code><code>/jenkins</code> <code>start</code>

<code>2016-08-26T11:13:56.839747+08:00 localhost [audit root</code><code>/23038</code> <code>as root</code><code>/23038</code> <code>on pts</code><code>/3/172</code><code>.16.100.57:51374-&gt;10.10.10.202:22] </code><code>/opt/sonar/conf</code><code>: </code><code>ps</code> <code>-ef | </code><code>grep</code> <code>jenkins</code>

<code>2016-08-26T11:28:36.159554+08:00 localhost [audit root</code><code>/19576</code> <code>as root</code><code>/19576</code> <code>on pts</code><code>/2/172</code><code>.16.100.216:57196-&gt;10.10.10.202:22] </code><code>/root</code><code>: </code><code>tail</code> <code>/var/log/userlog</code><code>.info</code>

本文轉自 曾哥最愛 51CTO部落格,原文連結:http://blog.51cto.com/zengestudy/1842879,如需轉載請自行聯系原作者