通过服务器日志溯源web应用攻击路径
作者:admin | 时间:2017-7-4 03:51:21 | 分类:黑客技术 隐藏侧边栏展开侧边栏
无论是我们使用的个人计算机还是服务器都为我们提供了强大的日志记录功能。例如系统日志,可以为我们记录系统硬件、软件和系统问题的信息,用户可以通过它来检查错误发生的原因,或者寻找受到攻击时攻击者留下的痕迹。
而服务器日志,则主要包括访问日志和错误日志。访问日志记录了该服务器所有的请求的过程,主要记录的是客户的各项信息,如访问时间、内容、地址等。错误日志则记录服务器出错的细节等数据。同时,这些日志记录信息也为安全事件的取证分析提供了强有力的证据和溯源的渠道。
我们以Web服务器为例。最常见的Apache HTTP Server一般会为我们提供两个主要的日志文件 – access.log和error.log。access.log记录所有文件请求。如果访问者请求www.example.com/main.php,则日志文件中将添加以下条目。
88.54.124.17 - - [16/Apr/2016:07:44:08 +0100] "GET /main.php HTTP/1.1" 200 203 "-" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"
从以上日志可以看出,一个访问者在2016年4月16日的07:44分成功请求了main.php文件。
试想该访问者请求的不是一个普通文件,而是一个转储数据库的文件例如dump_database.php。如果没有日志文件,那么我们可能永远不会发现有人或许已经将我们的重要数据窃取了。
下面让我通过一个简单的示例来为大家演示下,如何通过一个日志文件溯源web应用的攻击者。
调查
我们假设我们运行的一个最新的WordPress站点受到了黑客的攻击,并且该站点运行在没有任何补丁问题的Ubuntu服务器上。
在接到任务后,为了防止系统及其当前的日志状态发生改变,以及阻止攻击者可能的远程访问和与其他机器的网络交互,我们的分析取证小组首先对服务器进行了“离线”操作。
注:按照正常流程我们需要创建一个当前系统的副本,但由于我们是以演示为目的故跳过该步骤的操作,我们将直接以原始数据为演示对象。
寻找蛛丝马迹
在调查取证之前,我们首先要知道哪些证据是我们所需要的。通常攻击者都会直接访问一些“隐藏”或特殊的文件,或需要身份验证的管理区域,远程执行代码,SQL注入,文件包含,跨站点脚本(XSS)等异常行为,这就表明有攻击者可能利用了漏扫工具或手工对我们的站点进行了探测。
这里我们假设我们的access.log日志文件保存完好并且可用。
root@secureserver:/var/log/apache2# less access.log
access.log往往是一个相当大的文件,通常包含了数千条的请求记录。
84.55.41.57 - - [16/Apr/2016:20:21:56 +0100] "GET /john/index.php HTTP/1.1" 200 3804 "-" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0" 84.55.41.57 - - [16/Apr/2016:20:21:56 +0100] "GET /john/assets/js/skel.min.js HTTP/1.1" 200 3532 "http://www.example.com/john/index.php" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0" 84.55.41.57 - - [16/Apr/2016:20:21:56 +0100] "GET /john/images/pic01.jpg HTTP/1.1" 200 9501 "http://www.example.com/john/index.php" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0" 84.55.41.57 - - [16/Apr/2016:20:21:56 +0100] "GET /john/images/pic03.jpg HTTP/1.1" 200 5593 "http://www.example.com/john/index.php" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"
面对数量如此庞大的记录信息,如果我们每一行都去仔细查看显然不是个明智的选择。因此,我们可以将一些没有什么太大价值的数据给去除掉,例如图像、CSS、JavaScript这类文件。
由于我们的演示站点为WordPress,所以我们可以通过筛选的方式找出所有具有WordPress特征的access.log记录。
root@secureserver:~#cat /var/log/apache2/access.log | grep -E "wp-admin|wp-login|POST /"
以上命令将过滤access.log,并只显示包含wp-admin的字符串的记录,wp-admin是WordPress的默认后台管理文件夹,wp-login则是WordPress(wp-login.php)登录文件的一部分。最后的POST将筛选出所有通过POST方法发送的HTTP请求,这些请求很可能是在提交登录表单。
筛选完成后以下的日志记录引起了我们的注意:
84.55.41.57 - - [17/Apr/2016:06:52:07 +0100] "GET /wordpress/wp-admin/ HTTP/1.1" 200 12349 "http://www.example.com/wordpress/wp-login.php" "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"
我们看到IP为84.55.41.57的访问者,成功访问了WordPress的管理后台。
针对该IP我们继续筛选有关它的信息:
root@secureserver:~#cat /var/log/apache2/access.log | grep 84.55.41.57
我们得到了以下过滤内容:
84.55.41.57 - - [17/Apr/2016:06:57:24 +0100] "GET /wordpress/wp-login.php HTTP/1.1" 200 1568 "-"
84.55.41.57 - - [17/Apr/2016:06:57:31 +0100] "POST /wordpress/wp-login.php HTTP/1.1" 302 1150 "http://www.example.com/wordpress/wp-login.php"
84.55.41.57 - - [17/Apr/2016:06:57:31 +0100] "GET /wordpress/wp-admin/ HTTP/1.1" 200 12905 "http://www.example.com/wordpress/wp-login.php"
84.55.41.57 - - [17/Apr/2016:07:00:32 +0100] "POST /wordpress/wp-admin/admin-ajax.php HTTP/1.1" 200 454 "http://www.example.com/wordpress/wp-admin/"
84.55.41.57 - - [17/Apr/2016:07:00:58 +0100] "GET /wordpress/wp-admin/theme-editor.php HTTP/1.1" 200 20795 "http://www.example.com/wordpress/wp-admin/"
84.55.41.57 - - [17/Apr/2016:07:03:17 +0100] "GET /wordpress/wp-admin/theme-editor.php?file=404.php&theme=twentysixteen HTTP/1.1" 200 8092 "http://www.example.com/wordpress/wp-admin/theme-editor.php"
84.55.41.57 - - [17/Apr/2016:07:11:48 +0100] "GET /wordpress/wp-admin/plugin-install.php HTTP/1.1" 200 12459 "http://www.example.com/wordpress/wp-admin/plugin-install.php?tab=upload"
84.55.41.57 - - [17/Apr/2016:07:16:06 +0100] "GET /wordpress/wp-admin/update.php?action=install-plugin&plugin=file-manager&_wpnonce=3c6c8a7fca HTTP/1.1" 200 5698 "http://www.example.com/wordpress/wp-admin/plugin-install.php?tab=search&s=file+permission"
84.55.41.57 - - [17/Apr/2016:07:18:19 +0100] "GET /wordpress/wp-admin/plugins.php?action=activate&plugin=file-manager%2Ffile-manager.php&_wpnonce=bf932ee530 HTTP/1.1" 302 451 "http://www.example.com/wordpress/wp-admin/update.php?action=install-plugin&plugin=file-manager&_wpnonce=3c6c8a7fca"
84.55.41.57 - - [17/Apr/2016:07:21:46 +0100] "GET /wordpress/wp-admin/admin-ajax.php?action=connector&cmd=upload&target=l1_d3AtY29udGVudA&name%5B%5D=r57.php&FILES=&_=1460873968131 HTTP/1.1" 200 731 "http://www.example.com/wordpress/wp-admin/admin.php?page=file-manager_settings"
84.55.41.57 - - [17/Apr/2016:07:22:53 +0100] "GET /wordpress/wp-content/r57.php HTTP/1.1" 200 9036 "-"
84.55.41.57 - - [17/Apr/2016:07:32:24 +0100] "POST /wordpress/wp-content/r57.php?14 HTTP/1.1" 200 8030 "http://www.example.com/wordpress/wp-content/r57.php?14"
84.55.41.57 - - [17/Apr/2016:07:29:21 +0100] "GET /wordpress/wp-content/r57.php?29 HTTP/1.1" 200 8391 "http://www.example.com/wordpress/wp-content/r57.php?28"
84.55.41.57 - - [17/Apr/2016:07:57:31 +0100] "POST /wordpress/wp-admin/admin-ajax.php HTTP/1.1" 200 949 "http://www.myw ebsite.com/wordpre ss/wp-admin/admin.php?page=file-manager_settings"
让我们来分析一下这些记录。
攻击者访问登录界面。
84.55.41.57 - GET /wordpress/wp-login.php 200
攻击者提交了登录表单(使用POST方法的HTTP请求),并被重定向(302 HTTP状态代码)。
84.55.41.57 - POST /wordpress/wp-login.php 302
攻击者被成功重定向到了wp-admin(WordPress仪表盘),这意味着攻击者成功进行了身份验证。
84.55.41.57 - GET /wordpress/wp-admin/ 200
攻击者导航到了主题编辑器。
84.55.41.57 - GET /wordpress/wp-admin/theme-editor.php 200
攻击者试图通过编辑404文件将恶意代码插入到该页面,但由于缺乏写入权限最终没能成功。
84.55.41.57 - GET /wordpress/wp-admin/theme-editor.php?file=404.php&theme= twentysixteen 200
攻击者访问了插件安装程序。
84.55.41.57 - GET /wordpress/wp-admin/plugin-install.php 200
攻击者安装并激活了文件管理器插件。
84.55.41.57 - GET /wordpress/wp-admin/update.php?action=install-plugin&plugin= file-manager &_wpnonce=3c6c8a7fca 200 84.55.41.57 - GET /wordpress/wp-admin/plugins.php?action=activate&plugin=file-manager%2Ffile-manager.php&_wpnonce=bf932ee530 200
攻击者使用文件管理器插件上传了一个名为r57.php的文件,这很可能是一个PHP webshell脚本。
84.55.41.57 - GET /wordpress/wp-admin/admin-ajax.php?action=connector& cmd= upload&target=l1_d3AtY29udGVudA&name%5B%5D=r57.php&FILES=&_=1460873968131 200
日志表明攻击者运行r57 shell脚本。查询字符串?1(攻击者运行了phpinfo();)和?28(攻击者获取到了服务列表)可以看出攻击者并没有发现什么感兴趣的东西。
84.55.41.57 - GET /wordpress/wp-content/r57.php 200 84.55.41.57 - POST /wordpress/wp-content/r57.php?1 200 84.55.41.57 - GET /wordpress/wp-content/r57.php?28 200
攻击者的最后一个动作是通过文件管理器插件编辑主题的索引文件,并用“HACKED!”替换了其中的内容。
84.55.41.57 - POST /wordpress/wp-admin/admin-ajax.php 200 - http://www. example.com/wordpress/wp-admin/admin.php?page=file-manager_settings
基于上述信息,我们可以大致判断攻击者对我们的站点做了什么操作。但这里有个非常重要的点绝对不能忽略,那就是假设我们的管理员密码并没有泄露,攻击者也没有尝试过暴破,那么攻击者又是如何获取到我们的登录凭证的呢?
当前的access.log文件并没有为我们提供任何线索。不过,我们分析的对象不仅限于这一个access.log文件。Apache HTTP Server为我们循环归档了旧的日志文件。打开/var/log/apache2/目录我们可以看到4个额外的日志文件。
首先,我们筛选出所有IP为84.55.41.57的日志记录。可以看到,其中几条记录显示我们的自定义插件遭到了SQL注入攻击。
84.55.41.57- - [14/Apr/2016:08:22:13 0100] "GET /wordpress/wp-content/plugins/custom_plugin/check_user.php?userid=1 AND (SELECT 6810 FROM(SELECT COUNT(*),CONCAT(0x7171787671,(SELECT (ELT(6810=6810,1))),0x71707a7871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a) HTTP/1.1" 200 166 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/4.0 (.NET CLR 3.5.30729)"
84.55.41.57- - [14/Apr/2016:08:22:13 0100] "GET /wordpress/wp-content/plugins/custom_plugin/check_user.php?userid=(SELECT 7505 FROM(SELECT COUNT(*),CONCAT(0x7171787671,(SELECT (ELT(7505=7505,1))),0x71707a7871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a) HTTP/1.1" 200 166 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/4.0 (.NET CLR 3.5.30729)"
84.55.41.57- - [14/Apr/2016:08:22:13 0100] "GET /wordpress/wp-content/plugins/custom_plugin/check_user.php?userid=(SELECT CONCAT(0x7171787671,(SELECT (ELT(1399=1399,1))),0x71707a7871)) HTTP/1.1" 200 166 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/4.0 (.NET CLR 3.5.30729)"
84.55.41.57- - [14/Apr/2016:08:22:27 0100] "GET /wordpress/wp-content/plugins/custom_plugin/check_user.php?userid=1 UNION ALL SELECT CONCAT(0x7171787671,0x537653544175467a724f,0x71707a7871),NULL,NULL-- HTTP/1.1" 200 182 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/4.0 (.NET CLR 3.5.30729)"
假设该插件是站点管理员在网上随意复制粘贴创建的。该脚本旨在根据给定的ID检查用户的有效性。该插件在网站的主页上暴露了一个表单,该表单向/wordpress/wp-content/plugins/custom_plugin/check_user.php发送了一个AJAX GET请求。
通过对check_user.php脚本的分析发现,脚本写得并不严谨且存在SQL注入漏洞。
<?php //Include the WordPress header include('/wordpress/wp-header.php'); global $wpdb; // Use the GET parameter ‘userid’ as user input $id=$_GET['userid']; // Make a query to the database with the value the user supplied in the SQL statement $users = $wpdb->get_results( "SELECT * FROM users WHERE user_id=$id"); ?>
从access.log中的记录数量和注入语句判断,攻击者很可能是借助了某类SQL注入工具来利用该SQL注入漏洞。
在本文我们将不会深入探讨SQL注入攻击,以及如何修复SQL注入漏洞,想要了解更多内容可以点击该链接。以下是我们在当前日志中发现的记录:
/wordpress/wp-content/plugins/my_custom_plugin/check_user.php?userid=-6859 UNION ALL SELECT (SELECT CONCAT(0x7171787671,IFNULL(CAST(ID AS CHAR),0x20),0x616474686c76,IFNULL(CAST(display_name AS CHAR),0x20),0x616474686c76,IFNULL(CAST(user_activation_key AS CHAR),0x20),0x616474686c76,IFNULL(CAST(user_email AS CHAR),0x20),0x616474686c76,IFNULL(CAST(user_login AS CHAR),0x20),0x616474686c76,IFNULL(CAST(user_nicename AS CHAR),0x20),0x616474686c76,IFNULL(CAST(user_pass AS CHAR),0x20),0x616474686c76,IFNULL(CAST(user_registered AS CHAR),0x20),0x616474686c76,IFNULL(CAST(user_status AS CHAR),0x20),0x616474686c76,IFNULL(CAST(user_url AS CHAR),0x20),0x71707a7871) FROM wp.wp_users LIMIT 0,1),NULL,NULL--
以上的这些信息表明了,我们的数据库已经受到了严重的威胁并且我们的重要数据可能也已经被攻击者所窃取。
分析
通过以上的日志分析,我们已经可以大致的还原攻击者的攻击路径了。如下:
但还有一些问题我们仍没有答案,比如背后攻击者的真实身份是什么。在这一点上我们只获取到了攻击者的IP地址,但该IP地址极有可能是攻击者使用的一个代理/匿名IP(如Tor)。
在本文的示例中攻击者为我们留下了大量的证据和记录,而在实际环境中攻击者可能会清除所有的关键信息,这势必会加大调查人员的取证难度。
总的来说导致这次SQL注入攻击,归根于自定义WordPress插件中不安全的代码编写。其次,如果网站管理员能够定期对网站进行安全检查,那么也能在一定程度上避免此类事件的发生。
*参考来源:dzone,FB小编 secist 编译