通過伺服器日誌溯源定位web應用攻擊路徑

天府雲創發表於2017-07-03

無論是我們使用的個人計算機還是伺服器都為我們提供了強大的日誌記錄功能。例如系統日誌,可以為我們記錄系統硬體、軟體和系統問題的資訊,使用者可以通過它來檢查錯誤發生的原因,或者尋找受到攻擊時攻擊者留下的痕跡。

而伺服器日誌,則主要包括訪問日誌和錯誤日誌。訪問日誌記錄了該伺服器所有的請求的過程,主要記錄的是客戶的各項資訊,如訪問時間、內容、地址等。錯誤日誌則記錄伺服器出錯的細節等資料。同時,這些日誌記錄資訊也為安全事件的取證分析提供了強有力的證據和溯源的渠道。

我們以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伺服器上。

post-attack-log-1.png

在接到任務後,為了防止系統及其當前的日誌狀態發生改變,以及阻止攻擊者可能的遠端訪問和與其他機器的網路互動,我們的分析取證小組首先對伺服器進行了“離線”操作。

注:按照正常流程我們需要建立一個當前系統的副本,但由於我們是以演示為目的故跳過該步驟的操作,我們將直接以原始資料為演示物件。

尋找蛛絲馬跡

在調查取證之前,我們首先要知道哪些證據是我們所需要的。通常攻擊者都會直接訪問一些“隱藏”或特殊的檔案,或需要身份驗證的管理區域,遠端執行程式碼,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--

以上的這些資訊表明了,我們的資料庫已經受到了嚴重的威脅並且我們的重要資料可能也已經被攻擊者所竊取。

分析

通過以上的日誌分析,我們已經可以大致的還原攻擊者的攻擊路徑了。如下:

post-attack-log-2.png

但還有一些問題我們仍沒有答案,比如背後攻擊者的真實身份是什麼。在這一點上我們只獲取到了攻擊者的IP地址,但該IP地址極有可能是攻擊者使用的一個代理/匿名IP(如Tor)。

在本文的示例中攻擊者為我們留下了大量的證據和記錄,而在實際環境中攻擊者可能會清除所有的關鍵資訊,這勢必會加大調查人員的取證難度。

總的來說導致這次SQL隱碼攻擊,歸根於自定義WordPress外掛中不安全的程式碼編寫。其次,如果網站管理員能夠定期對網站進行安全檢查,那麼也能在一定程度上避免此類事件的發生。

相關文章