例行安全檢測 — 加固WordPress

因為我正在使用 cloudflare 提供的內網穿透服務, 相當於整個服務器只對外開放了 Web 服務, 所以我基本是圍繞 Web 服務在加固. 如果讀者的 wordpress 跑在租用的 VPS 上, 極有可能同時開放了數據庫、SSH、FTP 服務, 對這些的防護不在本文討論範圍內.

本文主要是參考了這篇官方教程. 如果你英文好的話, 不妨自己讀一讀這篇教程, 寫的很詳細, 基本每一個改動都有解釋.

檢測手段

https://github.com/wpscanteam/wpscan

下載 wpscan, 然後在終端敲入

wpscan --url https://example.com

可能需要關閉 CF 防火牆.

刪除無關文件

cd /www/wordpress

# 刪除根目錄下無關文件
rm readme.html
rm license.txt

# 遞歸刪除插件、主題 Readme
find . -name readme.txt -type f -print -exec rm -rf {} \;

檢查用戶權限

關於用戶權限說明, 請跳轉至 wordpress 官方教程

默認情況下, 目錄權限應當是 755 (drwxr-xr-x), 文件權限 644 (-rw-r–r–), 由一個專門的非管理員帳戶管理 (通常是www).

要更改權限, 請使用以下命令:

# 對於目錄
find /path/to/your/wordpress/install/ -type d -exec chmod 755 {} \; 

# 對於文件
find /path/to/your/wordpress/install/ -type f -exec chmod 644 {} \; 

保護 wordpress 文件

所謂的保護 wordpress 文件, 並不是防止訪客訪問這些文件, 而是防止出內鬼. ( PHP 腳本 ) 訪客在訪問這些文件時要麽是 403 要麽就是空白, 而網站內的 PHP 腳本則可能有權限讀取並修改它們.

下述的 .htaccess 只存在於使用 Apache 提供服務的服務器中. 如果你是使用 Nginx 或者其他軟件, 下述教程並不適合你.

保護 wp-includes

wp-includes 的概念類似頭文件, 屬於 include-only, 這一整個文件夾的內容都不應該被修改. 為了防止惡意插件或者惡意主題搞破壞, 可以在 .htaccess 中添加如下幾行:

# Block the include-only files.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

注意把上述內容添加在 BEGIN...END... 之外, 不然可能遭到複寫.

保護 wp-config.php

在 .htaccess 文件的開頭添加如下內容:

<files wp-config.php>
order allow,deny
deny from all
</files>

關閉編輯文件功能

我因為可以使用 ftp、vscode 遠程編輯, 並沒有怎麼在意過 wordpress 自帶的 「主題編輯器」和「插件編輯器」, 所以關掉也無所謂. 如果你對這些功能重度依賴, 我並不推薦關閉: 因為這項設置是防止已經獲得後台訪問權限的黑客亂改文件, 而都能進入後台的黑客估計也不是非要通過圖形編輯器來幹掉你的網站.

要關閉這項功能, 在 wp-config.php 中加入

define('DISALLOW_FILE_EDIT', true);

這個設置並沒有關掉插件對文件的寫入權限, 所以插件應該都還能正常工作.

保護 wp-admin.php

被 Cloudflare 防火牆擋下來一大部分攻擊都是針對 wp-login.php

所謂的攻擊, 大多數都是在暴力枚舉密碼, 比如說 admin/123456 這樣子.
當然我不怕這樣的攻擊, 首先我的用戶名就不是 admin, 其次我有自信自己的密碼在互聯網上是獨一無二的 ( cat /proc/sys/kernel/random/uuid ). 只不過煩倒是蠻煩的, 帶寬本身就有限還要和這群工具小子打交道?

解決方案就是編輯 .htaccess , 添加訪問口令.

通過直接編輯 .htaccess

  1. 狂戳這個鏈接, 根據 apache 版本生成 .htpasswd 文件.
  2. 它會生成一個字符串. 在網站根目錄創建一個 .htpasswd 文件站貼進去.
  3. 在 .htaccess 中添加如下內容 (仍然在 BEGIN 和 END 之外)
# Stop Apache from serving .ht* files
<Files ~ "^\.ht">
  Order allow,deny
  Deny from all
</Files>
# Protect wp-login.php
<Files wp-login.php>
  AuthUserFile [path]/.htpasswd
  AuthName "Private access"
  AuthType Basic
require user [username]
</Files>

注意修改框出來的內容, [path] 填網站根目錄絕對路徑, [username] 填認證的用戶名.

這樣就 OK. 這樣子如果不通過驗證, 訪問 wp-login.php 就顯示 500 錯誤.
另外, 那個 .htpasswd 文件是允許多行的, 一行對應一個用戶, 就這個樣子.

阻止垃圾留言

點擊提交留言的按鈕, WordPress 會跳轉到 wp-comments-post.php 來提交留言. 但是直接 POST 到這個地址也可以提交留言. (機器人) 但是直接 POST 沒有 referrer, 下面這個方法可以阻擋沒有 referrer 的 POST 操作.

# Stop spam attack logins and comments
<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteCond %{REQUEST_METHOD} POST
	RewriteCond %{REQUEST_URI} .(wp-comments-post|wp-login)\.php*
	RewriteCond %{HTTP_REFERER} !.*[example.com].* [OR]
	RewriteCond %{HTTP_USER_AGENT} ^$
	RewriteRule (.*) http://%{REMOTE_ADDR}/$1 [R=301,L]
</ifModule>

同樣, 替換 [example.com] 為實際網址.

做完了之後不要忘記開隱私模式測試一下.