資安

WordPress 站點地址被惡意篡改的防護方案討論

WordPress 站點的安全性非常重要,稍有不慎就有可能受到惡意攻擊。一種常見的手段是通過篡改站點的地址,於是用戶訪問網站時將會被重新定向到惡意網站。

惡意網站示意

一般情況下,有 2 種手段可以達到這個目的,下面就讓長老帶領大家一步步去看整個攻擊手段是如何實施的,並找到每個環節的安全防護措施,大家可以根據自己的情況使用其中的某個或多個防護措施。也歡迎大家留言分享各自的防護心得。

第一種攻擊手段是在文件中寫入惡意代碼。

該惡意代碼的表現形式為在網頁加載時執行一段 JS 代碼, 跳轉到惡意網址。

儘管我們可以保證自己購買的插件和主題都是正版軟件,我們也無法保證插件和主題沒有任何安全漏洞。一部分國產主題為了激活的校驗以及防止盜版,往往會故意留下一個口子,用來往數據庫中寫入授權信息,再加上 WordPress 的插件和主題文件本身就被設計成了可以被修改的,所以這樣的口子就會成為一個危險的入口。

最根本的方法當然是及時修補這個漏洞,將插件和主題更新到最新版。但是在此之前,我們只能通過一些並不是“治本”的方法來阻止這件事情發生。

WordFence找到的惡意代碼

WordFence 之類的安全防護軟件也可以找到惡意代碼的源頭,但是很多惡意代碼並不是很顯而易見的,它會多次中轉,使得前面的代碼看上去都是非常正常的內容,這樣就算刪掉了最後的危險代碼,由於前面的代碼還在,所以過段時間就會死灰復燃。

如圖是在一個主題文件中插入惡意代碼的示例,惡意代碼十分隱晦,並不能直接通過搜索 <script> 關鍵字查找,而且要調用好幾層。

主題文件中插入的惡意代碼

注意這段代碼並不是通過 Unix Shell 執行的,而是被 PHP 執行的,所以,就算我們沒有給這個文件執行的權限,也依然無法阻止這段惡意代碼被執行。因此,「權限不要給太高」這個教訓在這兒並不好使,這不是權限上能解決的。

這段代碼通過 POST 請求去訪問了一個被 BASE64 加密的網址,然後將請求得到的內容寫到了一個名為 _a 的文件中,並將 _a 包含進了主題文件中,因此,只要主題被加載了,_a 也被加載了。

惡意代碼獲取的惡意代碼

獲取到的這段代碼被寫到了 <?php 後面,因此仍然會被作為 PHP 代碼執行。_a 是一段 Unix Shell 命令,通過 PHP 的 shell_exec() 執行了這段命令。命令通過 wget 請求了一個腳本,並執行了這個腳本。

這個危險的腳本做的事情是在 WordPress 的核心的幾個 index.php 的文件開始處,加上一段 <script src="bad_zzw.js"></script> 的文件,這樣當 WordPress 被加載時,就會執行這段 JS 代碼,去請求了 src="bad_zzw.js" 中的 JS,而 bad_zzw.js 的內容只有 2 行,包括了一句 windows.location,即將當前頁面重定向到一個惡意的鏈接頁面。

到這裡,我們得到了第一個防護措施,那就是 PHP 官方推薦的:禁用 shell_exec()

可是,萬一本機別的服務需要用到 shell_exec() 呢,這個雖然不安全,但是我卻不得不使用它。在沒有可能改變其他業務的情況下,這個函數不能被禁用。

那我們就要嘗試將主題文件和 WordPress 核心的文件設置為只讀了。

一般而言,文件的最小權限會被設置為 644640,即自己可讀寫、組內其他用戶只讀、組外用戶只讀(或者組外用戶無權限),不會給執行權限 x;而目錄的最小權限會被設置為 755 或者 750,對於目錄而言,x 不再表示執行,而是表示是否可以進入該目錄訪問其中的內容。

於是我們有了第二個防護措施,那就是將主題、插件文件夾遞歸地設置為只讀:首先 chown -R www:www . 確保整個目錄都在 www 用戶組內,然後 chmod 0640 -R . 遞歸地將目錄下的文件全部修改為 640 權限,最後 find -type d -exec chmod 0750 {} \; . 遞歸地找到目錄下所有的類型為目錄的,並調用 exec 將權限修改為 750

對於 WordPress,只讀的權限不會帶來任何問題,www 用戶組也足以完成全部的操作。只是需要注意的是,這樣將不再支持有文件讀寫操作的行為,例如插件的更新、例如某些插件需要在目錄中生成緩存或配置文件等。

第二種攻擊手段是修改數據庫的字段。

我們這裡不討論數據庫密碼洩露、數據庫管理面板漏洞這樣的問題,只考慮數據庫用戶和密碼足夠複雜,而攻擊者利用 WordPress 的「合法的」數據庫訪問操作來修改了數據庫的字段。由於所有的操作都是 WordPress 的「合法的」數據庫訪問,所以我們沒有辦法判斷這是惡意攻擊,還是正常的數據庫訪問(例如更新設置、讀寫文章)。

惡意攻擊通常會篡改 wp_options 中的 siteurl 值和 home 值,使得用戶訪問站點時,站點 URL 部分被替換成惡意網站,實現跳轉,並且由於 /wp-admin 的訪問也會校驗站點地址,所以我們甚至無法登錄後臺去修改回來。

網上有很多這樣的案例,並且也給出瞭解決方案。

網上參見的解決方案為:首先想辦法進入數據庫,不管是 phpMyAdmin 或者 Unix Shell 登錄。修改 WordPress 數據庫中 wp_options 表中的 siteurlhome,保存。這時候就可以登錄後臺了,只需要把確實的設置重新修改。

還可以修改 wp-config.php,通過 define('WP_HOME','https://www.jxtxzzw.com'); define('WP_SITEURL','https://www.jxtxzzw.com'); 來指定自己的站點地址。

這裡長老再說一種方法:修改數據表,增加觸發器。

CREATE DEFINER=`wp_user`@`localhost` TRIGGER `trg_update_wp_options_forbidden`
BEFORE UPDATE ON `wp_options`
FOR EACH ROW
IF (NEW.option_id IN (1,2,3,4)) THEN
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot update locked record';
END IF;

這個觸發器是在修改 wp_options 之前被觸發,如果新修改的值的 ID 是 1、2、3、4,那麼就令 SQL 執行超時,並輸出信息「Cannot update locked record」。

注意:① 添加觸發器需要較高級別的權限,你可以根據需要修改為 root。② 上面的 (1,2,3,4) 在我的數據表中對應 siteurlhomeblognameblogdescription,你可以根據自己的情況修改這些 ID,也可以直接指定 NEW.option_name。③ 你可以增加更多鎖定的字段,例如 userscanregisterWPLANGdate_format 等等。④ 添加觸發器前請先將內容修改為期望的值。⑤ 如果再次修改,需要先解除觸發器。

保存後,讓我們修改這個字段,發現已經不能修改了。

但這不會影響後臺的設置,當我們同時修改了後臺的「站點標題」和「新用戶默認角色」後點擊保存,我們發現沒有被鎖定的記錄仍然可以正常修改,而被鎖定的記錄仍保持了鎖定的內容。

如果你的興致到這裡就結束了,那麼,已經做好了防護,可以去玩啦。站點地址已經不能被篡改。

無法篡改站點地址

如果你還有興趣,那麼可以打開 SQL 的 general_log(這會保存下所有的 SQL 操作,文件大小增速很恐怖,記得及時關掉),去挖掘到底是什麼時候、被誰、執行了怎麼樣的一條指令,再配合其他的手段,一步一步定位真凶,並進一步地去將它繩之以法。

關鍵詞:WordPress,篡改,掛馬,惡意,攻擊,注入,跳轉,重定向,網址,siteurl,home,url,hacked,jump,redirect

摘要:WordPress 站點稍有不慎就有可能受到惡意攻擊。一種常見的手段是通過篡改站點的地址,用戶訪問網站時將會被重新定向到惡意網站。長老將分析兩種常見的攻擊手段:修改文件和修改數據庫,並分享一些安全防護的小技巧。

原文鏈接:https://www.jxtxzzw.com/archives/5572

Leave a Reply

Your email address will not be published. Required fields are marked *