前言
最近连着碰到几起Linux服务器的安全应急响应,之前这方面的经验也不是很足,都是平时刷刷大家写的文章靠着一些Linux下的基础知识去分析着这几次碰到的事件,事后想想,在面对这几次的应急事件有很多地方考虑的不是很全面,随写此文纪录下心中所想。尽量用系统本身最基础的功能完成前期应急取证的备份工作。
划重点
重要的事情说四遍
备份! 备份!备份!备份!
原始数据的备份在应急响应分析过程中的重要性不言而喻,但在这几次的应急事件中甲方爸爸貌似都忽略了这个问题,当我们到达现场的时候,甲方爸爸要么是已经将被入侵服务器糟蹋了一波,要么是备份了,也只备份了一波日志。
系统镜像备份
备份
- # dd if=/dev/sda of=bak.img
恢复
- # dd if=bak.img of=/dev/sdb
fdisk -l 查看磁盘分区情况
- # fdisk -lDisk /dev/sda: 8589 MB, 8589934592 bytes255 heads, 63 sectors/track, 1044 cylinders
- Units = cylinders of 16065 * 512 = 8225280 bytes
- Sector size (logical/physical): 512 bytes / 512 bytes
- I/O size (minimum/optimal): 512 bytes / 512 bytes
- Disk identifier: 0x000a7707
- Device Boot Start End Blocks Id System
- /dev/sda1 * 1 1013 8136891 8e Linux LVM
- /dev/sda2 1014 1044 249007+ 5 Extended
- /dev/sda5 1014 1044 248976 83 Linux
df -h 查看磁盘占用情况
- # df -hFilesystem Size Used Avail Use% Mounted on/dev/mapper/brokenwebapps-root 7.3G 5.8G 1.2G 84% /none 497M 176K 497M 1% /devnone 502M 12K 502M 1% /dev/shmnone 502M 300K 501M 1% /var/runnone 502M 0 502M 0% /var/locknone 502M 0 502M 0% /lib/init/rwnone 7.3G 5.8G 1.2G 84% /var/lib/ureadahead/debugfs
- /dev/sda5 228M 44M 173M 21% /boot
- /dev/sdb1 12G 159M 12G 2% /test
# dd if=/dev/sda of=bak.img 进行备份,等个几分钟,备份完成
备份完成后发送至我们的分析系统
- # scp bak.img root@192.168.232.132:/root/
挂载分析
- 分析系统环境 - kali
通过losetup命令虚拟一个loop设备挂载镜像
查看第一个空闲loop设备
- # losetup -f/dev/loop0
创建loop设备
- # losetup /dev/loop0 bak.img
- # fdisk -lDisk /dev/loop0: 8 GiB, 8589934592 bytes, 16777216 sectors
- Units: sectors of 1 * 512 = 512 bytes
- Sector size (logical/physical): 512 bytes / 512 bytes
- I/O size (minimum/optimal): 512 bytes / 512 bytes
- Disklabel type: dos
- Disk identifier: 0x000a7707Device Boot Start End Sectors Size Id Type
- /dev/loop0p1 * 63 16273844 16273782 7.8G 8e Linux LVM
- /dev/loop0p2 16273845 16771859 498015 243.2M 5 Extended
- /dev/loop0p5 16273908 16771859 497952 243.1M 83 Linux
通过fdisk -l 我们可以看到我们的镜像中有三个分区,所以我们需要将每个分区单独映射出来,然后再进行挂载。
这里通过kpartx来进行分区表的读取和映射
- # kpartx -av /dev/loop0
- add map loop0p1 (254:0): 0 16273782 linear 7:0 63add map loop0p2 (254:1): 0 2 linear 7:0 16273845add map loop0p5 (254:2): 0 497952 linear 7:0 16273908
映射完毕后我们通过
- ls -l /dev/mapper/
- lrwxrwxrwx 1 root root 7 Nov 6 07:46 brokenwebapps-root -> ../dm-3lrwxrwxrwx 1 root root 7 Nov 6 07:46 brokenwebapps-swap_1 -> ../dm-4crw------- 1 root root 10, 236 Nov 6 07:46 control
- lrwxrwxrwx 1 root root 7 Nov 6 07:46 loop0p1 -> ../dm-0lrwxrwxrwx 1 ro
查看下映射关系。Linux下的mapper设备是内核中提供的一种从逻辑设备到物理设备的映射机制,通过该设备我们可以很清楚的看到root分区所在位置
mount挂载
下面我们将root分区挂载到我们的test目录
- # mount /dev/mapper/brokenwebapps-root /test/
切换到test目录查看,整个文件系统已经被还原到我们的分析系统上
下面我们就可以在我们的分析系统上对被入侵主机进行更加深入的分析了
卸载
- # umount /dev/mapper/brokenwebapps-root卸载kpartx映射# kpartx -dv /dev/loop0若无法卸载可先通过lvremove命令卸载映射出的逻辑设备再通过kpartx卸载映射
- 卸载loop设备# losetup -a 查看当前创建的loop设备/dev/loop0: [2049]:2107674 (/root/bak.img)# losetup -d /dev/loop0 卸载
内存镜像备份
测试环境:
- Linux kali 4.9.0-kali4-amd64 #1 SMP Debian 4.9.30-2kali1 (2017-06-22) x86_64 GNU/Linux
在比较老的Linux上,通常内核版本为2.6以下的,应该是还可以通过dd命令进行内存镜像备份的
命令大概长这样:
- dd if=/dev/mem of=dumpmem.dd bs=1024
通过dd命令dump出/dev/mem设备的内容完成内存的备份,但是2.6以下版本的内核在平常可能不是太多见所以我也没具体测试这个命令导出的具体效果。
2.6及以上的版本由于Linux安全性要求,其开始限制我们直接对系统内存的访问。所以内存的备份我们可能要违背一下初心,需要引用第三方的模块来完成我们的工作
一开始我尝试使用的工具是fmem,他通过将自己加载到Linux内核中运行,通过创建/dev/fmem设备使我们可以继续使用dd命令来备份我们的内存。奈何我没编译成功,因为找的模拟环境为owasp的一个漏洞环境,然而其源已经连接不上了导致我无法去更新内核的开发包,也就没法编译成功了,转战kali,编译也出问题,大概也是内核版本不匹配,有机会在研究下能不能搞定他。
前面说到由于一开始用的环境无法更新内核开发包了,所以注明下以下的操作皆在kali下完成的,kali的具体内核版本开头已说明
在继续说内存镜像备份前先瞎说一波内核模块的加载,反正也不是什么正儿八经的讨论内核
先引用下度娘百科吧。
大概就可以理解为Linux的内核是一块支持热插拔的板卡,在其运行过程中我们可以随时插入一个功能板,为其扩展功能。在不用的时候我们又可以将这块功能板给拔掉。这样我们就可以在不用修改内核的情况下扩展了其功能。前面提到的fmem也是运用到了Linux内核的这个特性,下面要用的这个工具也是运行的这个特性。
在Linux中我们可以通过
lsmod 查看有哪些功能版正插在板卡上
insmod 插入一块新的功能版
rmmod 拔出一块功能版
内存备份工具LiME
https://github.com/504ensicslabs/lime
git下源码丢进kali里进行编译假设你编译有问题,比如类似的这种错误
- make -C /lib/modules/2.6.32-25-generic-pae/build M="/test/LiME/src" modules
- make[1]: Entering directory `/lib/modules/2.6.32-25-generic-pae/build'
- make[1]: *** No rule to make target `modules'. Stop.
- make[1]: Leaving directory `/lib/modules/2.6.32-25-generic-pae/build'make: *** [default] Erro
你可能需要这个命令
- apt-get install linux-headers-$(uname -r)
去安装当前内核的开发包完成LiME的编译
记得安装完内核开发包后前往/lib/modules/xxxx-amd64目录下查看有没有build和source的软链接
没有的话通过下面命令创建一下
- ln -s /usr/src/linux-headers-x.xx.x-x-amd64 build
- ln -s /usr/src/linux-headers-x.xx.x-x-common source
没什么其他错误的话我们就可以加载这个模块进行内存备份了
进入其src目录进行编译# makemake -C /lib/modules/4.9.0-kali4-amd64/build M="/root/Github/LiME/src" modules
- make[1]: Entering directory '/usr/src/linux-headers-4.9.0-kali4-amd64'
- Building modules, stage 2.
- MODPOST 1 modules
- LD [M] /root/Github/LiME/src/lime.ko
- make[1]: Leaving directory '/usr/src/linux-headers-4.9.0-kali4-amd64'strip --strip-unneeded lime.ko
- mv lime.ko lime-4.9.0-kali4-amd64.ko
编译成功后会在当前目录生成lime-4.9.0-kali4-amd64.ko文件
执行命令
- # insmod ./lime-4.9.0-kali4-amd64.ko "path=/test/testmem.lime format=lime"
稍等片刻完成内存的备份,其中path参数为备份内存保存的路径,format为保存格式,建议使用lime格式,方便我们后面通过volatility进行分析
简单的先测试下刚刚备份的内存是否可以被volatility识别
- # python vol.py -f /test/testmem.lime --profile=Linuxkalix64 limeinfoVolatility Foundation Volatility Framework 2.6
- Memory Start Memory End Size
- ------------------ ------------------ ------------------
- 0x0000000000001000 0x000000000009f3ff 0x000000000009e400
- 0x0000000000100000 0x00000000546dffff 0x00000000545e0000
- 0x0000000054700000 0x00000000547fffff 0x0000000000100000
内存备份完后卸载lime模块
很无奈的备份
安全应急实施过程中有时候甲方爸爸也不一定让你搞这搞那,一句话,你要啥日志~ 我~ 甲方爸爸~ 给日志~
这时难免被这王霸之气震惊,随记录下需要备份哪些日志以及文件以免遗漏
打包打包打包
/var/log完整打包
视具体情况而定,假设日志过多情况下,则可能需要我们进行筛选打包
- # tar -czvf xx_var_log_time.tar.gz /var/log
针对web入侵应急还需备份出web应用,nginx日志等
经常会遗漏的一些内容
备份passwd和shadow文件分析是否存在可疑账号
比如某些本该是系统用户的账号却存在了口令字段
- # cat /etc/passwd > etc_passwd.txt# cat /etc/shadow > etc_shadow.txt
备份当前网络连接情况# netstat -anp > netstat_anp.txt
备份历史命令# cp ~/.bash_history bash_history.txt带时间和执行者格式备份
- history# export HISTTIMEFORMAT="%Y-%m-%d:%H-%M-%S:`whoami`:"# history > history.txt
备份用户登录信息
- # w > col_users.txt# lastlog > lastlog.txt
查找最近5天被修改的文件#find / -type f -mtime +5
备份进程信息
- # ps -ef > ps_ef.txt# ps aux > ps_aux.txt
备份重要文件或命令的md5值
懒人办法:
设置要备份的目录# TESTDIR='/bin/'# find $TESTDIR -type f -print0 | xargs -0 md5sum > dir_bin_cmd.md5备份出bin目录下所有命令的md5值
生成完整的或自定义的某个目录文件系统树形结构图# tree > tree.txt或者定义生成目录深度# tree -L 2