WordPress 站點(diǎn)的安全性非常重要,稍有不慎就有可能受到惡意攻擊。一種常見的手段是通過篡改站點(diǎn)的地址,于是用戶訪問網(wǎng)站時(shí)將會(huì)被重新定向到惡意網(wǎng)站。

一般情況下,有 2 種手段可以達(dá)到這個(gè)目的,下面就讓長老帶領(lǐng)大家一步步去看整個(gè)攻擊手段是如何實(shí)施的,并找到每個(gè)環(huán)節(jié)的安全防護(hù)措施,大家可以根據(jù)自己的情況使用其中的某個(gè)或多個(gè)防護(hù)措施。也歡迎大家留言分享各自的防護(hù)心得。
第一種攻擊手段是在文件中寫入惡意代碼。
該惡意代碼的表現(xiàn)形式為在網(wǎng)頁加載時(shí)執(zhí)行一段 JS 代碼, 跳轉(zhuǎn)到惡意網(wǎng)址。
盡管我們可以保證自己購買的插件和主題都是正版軟件,我們也無法保證插件和主題沒有任何安全漏洞。一部分國產(chǎn)主題為了激活的校驗(yàn)以及防止盜版,往往會(huì)故意留下一個(gè)口子,用來往數(shù)據(jù)庫中寫入授權(quán)信息,再加上 WordPress 的插件和主題文件本身就被設(shè)計(jì)成了可以被修改的,所以這樣的口子就會(huì)成為一個(gè)危險(xiǎn)的入口。
最根本的方法當(dāng)然是及時(shí)修補(bǔ)這個(gè)漏洞,將插件和主題更新到最新版。但是在此之前,我們只能通過一些并不是“治本”的方法來阻止這件事情發(fā)生。

WordFence 之類的安全防護(hù)軟件也可以找到惡意代碼的源頭,但是很多惡意代碼并不是很顯而易見的,它會(huì)多次中轉(zhuǎn),使得前面的代碼看上去都是非常正常的內(nèi)容,這樣就算刪掉了最后的危險(xiǎn)代碼,由于前面的代碼還在,所以過段時(shí)間就會(huì)死灰復(fù)燃。
如圖是在一個(gè)主題文件中插入惡意代碼的示例,惡意代碼十分隱晦,并不能直接通過搜索 <script> 關(guān)鍵字查找,而且要調(diào)用好幾層。

注意這段代碼并不是通過 Unix Shell 執(zhí)行的,而是被 PHP 執(zhí)行的,所以,就算我們沒有給這個(gè)文件執(zhí)行的權(quán)限,也依然無法阻止這段惡意代碼被執(zhí)行。因此,「權(quán)限不要給太高」這個(gè)教訓(xùn)在這兒并不好使,這不是權(quán)限上能解決的。
這段代碼通過 POST 請(qǐng)求去訪問了一個(gè)被 BASE64 加密的網(wǎng)址,然后將請(qǐng)求得到的內(nèi)容寫到了一個(gè)名為 _a 的文件中,并將 _a 包含進(jìn)了主題文件中,因此,只要主題被加載了,_a 也被加載了。

獲取到的這段代碼被寫到了 <?php 后面,因此仍然會(huì)被作為 PHP 代碼執(zhí)行。_a 是一段 Unix Shell 命令,通過 PHP 的 shell_exec() 執(zhí)行了這段命令。命令通過 wget 請(qǐng)求了一個(gè)腳本,并執(zhí)行了這個(gè)腳本。
這個(gè)危險(xiǎn)的腳本做的事情是在 WordPress 的核心的幾個(gè) index.php 的文件開始處,加上一段 <script src="bad_zzw.js"></script> 的文件,這樣當(dāng) WordPress 被加載時(shí),就會(huì)執(zhí)行這段 JS 代碼,去請(qǐng)求了 src="bad_zzw.js" 中的 JS,而 bad_zzw.js 的內(nèi)容只有 2 行,包括了一句 windows.location,即將當(dāng)前頁面重定向到一個(gè)惡意的鏈接頁面。
到這里,我們得到了第一個(gè)防護(hù)措施,那就是 PHP 官方推薦的:禁用 shell_exec()。
可是,萬一本機(jī)別的服務(wù)需要用到 shell_exec() 呢,這個(gè)雖然不安全,但是我卻不得不使用它。在沒有可能改變其他業(yè)務(wù)的情況下,這個(gè)函數(shù)不能被禁用。
那我們就要嘗試將主題文件和 WordPress 核心的文件設(shè)置為只讀了。
一般而言,文件的最小權(quán)限會(huì)被設(shè)置為 644 或 640,即自己可讀寫、組內(nèi)其他用戶只讀、組外用戶只讀(或者組外用戶無權(quán)限),不會(huì)給執(zhí)行權(quán)限 x;而目錄的最小權(quán)限會(huì)被設(shè)置為 755 或者 750,對(duì)于目錄而言,x 不再表示執(zhí)行,而是表示是否可以進(jìn)入該目錄訪問其中的內(nèi)容。
于是我們有了第二個(gè)防護(hù)措施,那就是將主題、插件文件夾遞歸地設(shè)置為只讀:首先 chown -R www:www . 確保整個(gè)目錄都在 www 用戶組內(nèi),然后 chmod 0640 -R . 遞歸地將目錄下的文件全部修改為 640 權(quán)限,最后 find -type d -exec chmod 0750 {} \; . 遞歸地找到目錄下所有的類型為目錄的,并調(diào)用 exec 將權(quán)限修改為 750。
對(duì)于 WordPress,只讀的權(quán)限不會(huì)帶來任何問題,www 用戶組也足以完成全部的操作。只是需要注意的是,這樣將不再支持有文件讀寫操作的行為,例如插件的更新、例如某些插件需要在目錄中生成緩存或配置文件等。
第二種攻擊手段是修改數(shù)據(jù)庫的字段。
我們這里不討論數(shù)據(jù)庫密碼泄露、數(shù)據(jù)庫管理面板漏洞這樣的問題,只考慮數(shù)據(jù)庫用戶和密碼足夠復(fù)雜,而攻擊者利用 WordPress 的「合法的」數(shù)據(jù)庫訪問操作來修改了數(shù)據(jù)庫的字段。由于所有的操作都是 WordPress 的「合法的」數(shù)據(jù)庫訪問,所以我們沒有辦法判斷這是惡意攻擊,還是正常的數(shù)據(jù)庫訪問(例如更新設(shè)置、讀寫文章)。
惡意攻擊通常會(huì)篡改 wp_options 中的 siteurl 值和 home 值,使得用戶訪問站點(diǎn)時(shí),站點(diǎn) URL 部分被替換成惡意網(wǎng)站,實(shí)現(xiàn)跳轉(zhuǎn),并且由于 /wp-admin 的訪問也會(huì)校驗(yàn)站點(diǎn)地址,所以我們甚至無法登錄后臺(tái)去修改回來。
網(wǎng)上有很多這樣的案例,并且也給出了解決方案。
網(wǎng)上參見的解決方案為:首先想辦法進(jìn)入數(shù)據(jù)庫,不管是 phpMyAdmin 或者 Unix Shell 登錄。修改 WordPress 數(shù)據(jù)庫中 wp_options 表中的 siteurl 和 home,保存。這時(shí)候就可以登錄后臺(tái)了,只需要把確實(shí)的設(shè)置重新修改。
還可以修改 wp-config.php,通過 define('WP_HOME','https://www.jxtxzzw.com'); define('WP_SITEURL','https://www.jxtxzzw.com'); 來指定自己的站點(diǎn)地址。
這里長老再說一種方法:修改數(shù)據(jù)表,增加觸發(fā)器。
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;
這個(gè)觸發(fā)器是在修改 wp_options 之前被觸發(fā),如果新修改的值的 ID 是 1、2、3、4,那么就令 SQL 執(zhí)行超時(shí),并輸出信息「Cannot update locked record」。
注意:① 添加觸發(fā)器需要較高級(jí)別的權(quán)限,你可以根據(jù)需要修改為 root。② 上面的 (1,2,3,4) 在我的數(shù)據(jù)表中對(duì)應(yīng) siteurl、home、blogname 和 blogdescription,你可以根據(jù)自己的情況修改這些 ID,也可以直接指定 NEW.option_name。③ 你可以增加更多鎖定的字段,例如 userscanregister、WPLANG、date_format 等等。④ 添加觸發(fā)器前請(qǐng)先將內(nèi)容修改為期望的值。⑤ 如果再次修改,需要先解除觸發(fā)器。
保存后,讓我們修改這個(gè)字段,發(fā)現(xiàn)已經(jīng)不能修改了。
但這不會(huì)影響后臺(tái)的設(shè)置,當(dāng)我們同時(shí)修改了后臺(tái)的「站點(diǎn)標(biāo)題」和「新用戶默認(rèn)角色」后點(diǎn)擊保存,我們發(fā)現(xiàn)沒有被鎖定的記錄仍然可以正常修改,而被鎖定的記錄仍保持了鎖定的內(nèi)容。
如果你的興致到這里就結(jié)束了,那么,已經(jīng)做好了防護(hù),可以去玩啦。站點(diǎn)地址已經(jīng)不能被篡改。

如果你還有興趣,那么可以打開 SQL 的 general_log(這會(huì)保存下所有的 SQL 操作,文件大小增速很恐怖,記得及時(shí)關(guān)掉),去挖掘到底是什么時(shí)候、被誰、執(zhí)行了怎么樣的一條指令,再配合其他的手段,一步一步定位真兇,并進(jìn)一步地去將它繩之以法。
關(guān)鍵詞:WordPress,篡改,掛馬,惡意,攻擊,注入,跳轉(zhuǎn),重定向,網(wǎng)址,siteurl,home,url,hacked,jump,redirect
摘要:WordPress 站點(diǎn)稍有不慎就有可能受到惡意攻擊。一種常見的手段是通過篡改站點(diǎn)的地址,用戶訪問網(wǎng)站時(shí)將會(huì)被重新定向到惡意網(wǎng)站。長老將分析兩種常見的攻擊手段:修改文件和修改數(shù)據(jù)庫,并分享一些安全防護(hù)的小技巧。