WordPress 登入保護:5 招設定,由易到難一次做好

多數人設定 WordPress 後台防護,想到的第一件事都是把密碼設得又長又複雜。Microsoft 一份研究卻指出,帳號會不會被攻破,關鍵往往不在密碼夠不夠難猜,而在密碼之外還有沒有另一道關卡。只要多啟用一種驗證方式,帳號被攻破的風險就能降低九成九以上,這道反差,其實正說明了 WordPress 登入保護能做的設定,遠不只「密碼設難一點」,而是一整套由淺入深的動作。

這篇要一次講完五個具體做法:換掉登入網址、限制失敗次數、訂出密碼門檻、開啟二階段驗證,最後把可疑來源整個擋在門外。順序不是隨便排的,而是照上手難度由易到難走,前面幾招裝好外掛就生效,後面幾招牽涉角色政策或伺服器操作,需要多一點準備。每一招也會附上「什麼情境特別該優先做」的提醒,讓你照自己網站的規模和人力,決定先補哪一關。

先從為什麼登入這道關卡值得排在資安清單最前面講起,再一招一招往下拆。

WordPress 登入保護五招由易到難排列:換登入網址、限制失敗次數、訂密碼門檻、二階段驗證、鎖定可疑來源,疊成防禦縱深
五招依上手難度由易到難排列,每一招各補一個破口,疊在一起才構成完整的防禦縱深。

為什麼登入防護,該排在資安清單最前面?

WordPress 後台被盯上,通常不是因為有人特別討厭你的網站,而是因為每一台網站的登入頁面,長得都一樣。攻擊者手上跑的自動化程式不會挑對象,只會對著 /wp-login.php 或 /wp-admin 這種固定路徑,一批一批把帳號密碼組合丟進去試,今天掃過的網域,明天可能就換下一批。真正針對某個網站、某個人設計的攻擊反而是少數。搞清楚這個差異很重要,因為多數網站要防的其實是前者,也就是量大、不挑對象的自動化掃描,不是有人專程盯著你研究攻法。

這也是為什麼這篇要照上手難度把五招排出順序,而不是照重要度排。換掉登入網址、限制失敗次數這兩招,通常裝好外掛、改一個設定就生效,幾分鐘能做完;後面訂密碼門檻、開二階段驗證、鎖定可疑來源這三招,則牽涉角色權限的政策制定,或是伺服器與 CDN 層的操作,需要多一點時間準備。照這個順序做,可以先在最短時間內補起最容易處理的破口,再逐步往下處理比較花工夫的部分。

更重要的是,這五招裡沒有任何一招是萬能鑰匙。換了登入網址,攻擊者換一個管道還是能找到入口;開了二階段驗證,伺服器層如果沒設速率限制,還是可能因為大量惡意流量,拖垮整個網站的效能。資安圈把這種做法稱作「防禦縱深」,每一層只補一個破口,真正安全的做法是把好幾層疊在一起,讓攻擊者得同時突破每一關才有機會得手。這篇會一次講完五招,而不是只鑽研一招,原因就在這裡。後面每一節也會呼應這個立場,並附上「什麼情境特別該優先做」的判斷,幫你抓輕重緩急。第一個該補的破口,就藏在最前面這道門本身,也就是登入頁面用的網址。

招式一:換掉登入網址,把後台入口從公開路徑藏起來

WordPress 網站的登入頁面,預設都掛在同一個路徑,也就是 /wp-login.php,或是導向 /wp-admin 之後被要求輸入帳密。這件事對經營者來說習以為常,對攻擊者的自動化程式而言卻是天大的方便——不需要知道你的網站叫什麼名字、賣什麼、由誰經營,只要拿一份 WordPress 網站清單,對每一個網址後面補上同一段固定路徑,就能批次測試帳號密碼。

換掉登入網址,做的就是讓對方連「門」在哪裡都找不到。把登入頁面搬到一個只有你自己知道的路徑,原本的預設路徑改回傳 404 或轉址到別處。這是五招裡上手門檻最低的一步,通常裝一支外掛、設定一個新路徑,幾分鐘內就能生效,不需要動到資料庫欄位或伺服器設定。

不過要先說清楚,這招換的是「隱藏」,不是「消除」。原本的帳號密碼驗證邏輯完全沒變,只是攻擊者暫時找不到入口而已。一旦新的登入網址不小心流出去,比如某些外掛或主題把登入連結寫死在頁尾、或是不小心貼進共用的文件、聊天群組裡,防護力就整個歸零。也因為這樣,換登入網址不能單獨使用,而是要跟後面幾招疊在一起做,新網址設定好之後,也要記得檢查網站前後台有沒有殘留的舊登入連結。

實際操作上,常見做法是裝一支專門處理登入路徑的外掛,像是 WPS Hide Login 這類工具。這類外掛的運作原理是攔截進來的請求,把原本 /wp-login.php 的請求導向 404 頁面,再讓你設定的新路徑對應到真正的登入表單,並不是真的把 WordPress 核心裡的 wp-login.php 檔案改名或刪除,核心程式碼完全沒被動到,升級 WordPress 版本也不會受影響。

這招最適合還在用預設登入網址、前面又沒有 CDN 或 WAF 擋掉大量掃描流量的網站,優先度最高,幾乎是所有網站都該做的第一步。如果網站前面已經掛了 Cloudflare 之類的 CDN 或 WAF,把自動化掃描流量都攔在外面,這招帶來的邊際效益就會降低,可以往後排,先處理其他還沒補的破口。

順手關掉 XML-RPC,堵上另一個常被忽略的暴力破解放大器

換登入網址的同時,還有一個同樣容易被忽略的入口值得順手處理,就是 xmlrpc.php 這支檔案。國際資安公司 Sucuri 最早揭露一種利用 XML-RPC 裡 system.multicall 功能的攻擊手法。這個功能原本是設計來讓一次請求同時執行多個指令,但攻擊者拿它來把成百上千組帳號密碼包進同一個 HTTP 請求裡送出去試,等於用一次請求就跑完原本要送好幾百次的嘗試。

這種做法特別麻煩的地方在於,一般用來偵測登入失敗次數的機制,通常是根據 HTTP 請求的次數去計數,而 system.multicall 攻擊表面上只送了一次請求,實際上卻在裡面塞了幾百組帳密組合,很容易繞過只看請求次數的防護邏輯。Cloudflare 後續也針對這種攻擊手法發布過技術說明,證實這類放大攻擊確實會讓一般的登入失敗次數限制形同虛設。

system.multicall 把上百組帳密塞進一次 XML-RPC 請求,讓只算請求次數的登入限流形同虛設
一般暴力破解每次請求只試一組、容易被計數器擋下;system.multicall 一次請求塞上百組卻只被記一次,就繞過了限流(資料來源:Sucuri、Cloudflare)。

好消息是,多數網站其實用不到 XML-RPC 提供的功能,除非你有串接舊版的 WordPress 行動 App,或是某些需要遠端發文的第三方工具。對這類網站來說,直接關掉 XML-RPC 幾乎沒有副作用,是換登入網址時可以順手一起做的事。換完登入網址、關掉 XML-RPC 之後,下一個該處理的破口,是有人已經找到登入網址、開始不斷測試密碼組合的情況,這時候就輪到限制登入失敗次數上場。

招式二:設下登入失敗次數上限,擋下自動化帳密攻擊

限制登入失敗次數,概念其實很老派。同一個來源在一段時間內,密碼試錯太多次,就先擋一段時間再讓它繼續試,而不是放任攻擊程式無限次嘗試下去。這正是國際非營利組織 OWASP 在《Credential Stuffing Prevention Cheat Sheet》裡建議的基本作法之一,官方建議站台要對登入端點設限流機制,並依風險程度分級回應,而不是只倚賴密碼這一道防線。

WordPress 核心目前沒有內建這項設定的畫面,要另外處理才會生效。實際可行的做法分成兩層:一層是站台層,靠外掛在 WordPress 這一層擋;另一層是伺服器或 CDN 層,在請求還沒進到 WordPress 之前就先擋掉。兩層可以疊加使用,效果會比只做其中一層更完整,尤其流量夠大的網站,單靠站台層外掛容易拖累整體效能。

這裡也要提醒一個常被忽略的副作用,多數限流機制是以 IP 為單位計數,如果是辦公室或門市共用同一條對外網路線,只要有一個人不小心打錯密碼太多次,可能會連累同事一起被鎖在外面,登入不了後台。設定鎖定門檻時,這點要納入考量,別把門檻設得太緊而誤傷自己人。

這招幾乎是所有 WordPress 網站都該做的基本動作,只要站點會被自動化程式掃描到就用得上,可以說是開二階段驗證之前的過渡防線,但不能拿來取代二階段驗證,兩者要疊在一起才完整。

用外掛設定鎖定門檻與鎖定時間

站台層最常見的做法,是裝一支專門處理登入次數限制的外掛,設定兩個關鍵數字:失敗幾次觸發鎖定、鎖多久才能再試。國際教學平台 WPBeginner 整理過這類工具常見的預設值:失敗 4 次就鎖定 20 分鐘,如果同一個來源反覆觸發、被鎖滿 4 次,鎖定時間會拉長到 24 小時。

登入失敗累計到四次觸發鎖定二十分鐘,同來源反覆觸發鎖滿四輪後拉長到二十四小時
限制登入失敗次數的常見機制:試錯滿四次先鎖二十分鐘,反覆觸發就把封鎖時間拉長到二十四小時(資料來源:WPBeginner)。

不過這只是起始值,實際要不要調整,得看網站型態。單純的個人部落格,用預設值通常就夠用;電商或有金流交易的網站可以調得更緊,例如失敗 3 次就鎖、鎖 20 到 30 分鐘,重複觸發的來源直接鎖到近乎永久封鎖。高流量或企業型網站則反過來,容許的失敗次數要設得更少,但同時要更小心,別把正常使用者的偶爾手誤也一起鎖掉。

還有一點容易被忽略,如果網站前面已經掛了 Cloudflare 之類的 CDN 或 WAF,外掛在 WordPress 這一層看到的來源 IP,很可能是 CDN 節點本身的 IP,而不是訪客真正的來源 IP。這種情況下,得另外設定讓 WordPress 讀取正確的訪客 IP 標頭,不然限流機制等於在跟錯的對象計數,防護效果會大打折扣。

在伺服器或 CDN 層,再加一道防線

外掛終究只在 WordPress 這一層運作,如果攻擊流量夠大,或是來自大量分散的 IP,靠站台層外掛已經不太夠用,更前置的防線會更有效果。這裡有兩條路可以走。

第一條路是自架主機或 VPS 常見的 fail2ban 做法。它的運作邏輯是持續讀取伺服器的登入紀錄檔案,比對出符合失敗模式的 IP,例如同一個來源在短時間內連續登入失敗,一旦符合條件,就自動在防火牆層加一條規則把這個 IP 封鎖起來,時間到了再自動解除。這個做法的優點是攻擊請求在防火牆層就被擋掉,根本進不到 WordPress 程式碼,伺服器資源不會被消耗;限制則是它得先等紀錄寫進 log 檔案之後才會反應,最初的幾次嘗試還是會先被放行,不是完全即時。

第二條路是有掛 CDN 或 WAF 的網站,像 Cloudflare,可以直接對登入頁面設定速率限制規則。Cloudflare 官方文件裡就有現成的「保護登入」一鍵規則可以套用,原本的門檻設定是 5 分鐘內同一個來源送出超過 5 次 POST 請求,就把這個來源封鎖 15 分鐘,可以作為速率限制門檻的具體參考。這兩條路並不衝突,如果網站前面已經有 CDN,兩層可以一起做,伺服器層跟 CDN 層各擋一道。把攻擊擋在門外的功夫做得差不多之後,下一步要處理的,是每個帳號本身用的密碼夠不夠禁得起測試,這就是密碼門檻要上場的地方。

招式三:訂出全站密碼門檻,交給制度而不是個人習慣

前面兩招處理的是「擋攻擊」,這一招要處理更基本的問題,也就是網站上每一個帳號的密碼本身夠不夠強。這裡要跟「密碼設長一點」這種個人選擇層次的建議拉開距離,講的是網站經營者怎麼從制度面,確保每一個有權限登入後台的帳號都達到一定標準,而不是各自看著辦。

先講一個常被忽略的現況,WordPress 後台新增或修改密碼時,雖然會顯示一條密碼強度計,從弱到強跑出顏色與文字,但這條計量表只是顯示,並不會真的擋下弱密碼。使用者就算選了系統標示「非常弱」的密碼,一樣可以按下儲存,WordPress 核心不會阻止這個動作。換句話說,密碼強度計比較像一個建議,不是一道守門的關卡。

在 WordPress 個人資料頁把新密碼設成弱密碼,強度計顯示最低強度,仍能勾選確認後儲存
WordPress 個人資料頁的密碼強度計只會顯示強弱,就算標成最低強度,勾選確認後照樣能存檔——它是建議、不是守門關卡。

如果網站只有經營者自己一個帳號在用,這個問題可以簡化處理,自己選一組夠長的密碼就好,不必特別制度化。但只要網站有多位作者或編輯共用後台,或是幫客戶代管網站、開放協力廠商登入,制度化的密碼門檻就變成必要動作,不能只靠提醒大家密碼設難一點這種口頭約定。

依角色分級,未達標就強制要求更新密碼

實際操作上,做法是裝一支密碼政策管理類的外掛,依角色分別設定門檻,例如管理員要求更高強度、編輯次之,其他角色再依需要調整。這類外掛通常會檢查既有帳號的密碼是否達標,如果沒有達到設定的門檻,會在該帳號下次登入時強制要求先改密碼才能繼續使用後台,而不是只對新申請的帳號生效,確保舊帳號也一併補上門檻。

這裡有個實務提醒,導入這項政策前,最好先跟團隊說一聲,讓大家知道接下來登入可能會被要求改密碼,避免同事某天登入時突然卡在改密碼畫面,誤以為自己的帳號被入侵或出了問題。

擋掉已經外流的密碼,而不是只要求「夠複雜」

NIST 在最新一版《數位身分準則》(SP 800-63B)裡,對密碼政策的重點跟過去不太一樣,主張與其強制要求密碼一定要有大小寫加符號,不如直接擋掉「已知外流」或「常見猜測」的密碼名單。原因很直接,複雜度規則常常被使用者用同一套公式繞過,例如固定在單字後面加一個驚嘆號跟兩位數字,表面上符合規則,實際上防禦力有限;而一旦密碼本身已經出現在某次資料外流事件的資料庫裡,不管它看起來多複雜,攻擊者一樣能直接拿去試。

這份準則也對密碼長度給出具體門檻,依驗證方式不同而不同,如果密碼是唯一的驗證方式,單因子密碼至少要 15 碼;如果密碼是搭配二階段驗證這類多重驗證一起使用,最低門檻可以放寬到 8 碼。這個差異也呼應這篇的整體邏輯,密碼不是唯一的防線,搭配其他驗證方式之後,單一防線的門檻本來就可以適度調整。

NIST 建議密碼長度依驗證方式而定:單因子至少十五碼、搭配二階段驗證最低八碼,並優先擋已外流密碼
依 NIST SP 800-63B,密碼是唯一防線時至少十五碼、搭配二階段驗證可放寬到八碼,而擋掉已外流與常見密碼比硬性複雜度規則更有效(資料來源:NIST SP 800-63B)。

NIST 準則另外也建議,如果沒有帳號外流的跡象,不必強制要求使用者定期更換密碼。道理跟前面擋外流密碼名單一致,制度真正該擋下的是實際存在的風險,不是為了形式上看起來有在管理而增加使用者的負擔。定期強制換密碼常常只換出一組跟舊密碼差不多、規律性很好猜的新密碼,防禦力並沒有真的提升。密碼門檻顧好之後,再往前一步要處理的,是就算密碼真的外流,帳號也不會因此被攻破,這正是二階段驗證要扛起的工作。

招式四:加開二階段驗證,密碼外流也進不去

這篇一開始提到,Microsoft 的研究發現帳號會不會被攻破,關鍵往往不在密碼夠不夠難猜。現在可以把這個論點攤開講清楚。Microsoft 針對自家 Azure Active Directory 帳號做的大規模研究指出,開啟多重驗證能讓帳號被攻破的整體風險降低 99.22%,即使是密碼已經外流的帳號,開啟多重驗證後風險仍能降低 98.56%。換句話說,就算攻擊者手上真的握有正確的密碼,只要帳號多開了一道驗證關卡,絕大多數情況下還是進不去。這正是二階段驗證在整套登入保護裡最關鍵的一步,密碼再強都只能算半套防護,搭配二階段驗證才算完整。

開啟二階段驗證後,握有外流密碼的攻擊者仍過不了驗證碼這一關,被擋在 WordPress 後台之外
開啟二階段驗證後,你靠驗證器 App 的驗證碼順利登入,握有外流密碼的攻擊者卻卡在第二關;整體被攻破風險可降九成九以上(資料來源:Microsoft)。

實際設定上,目前最普及也不用額外付費的方式,是搭配驗證器 App 產生的一次性密碼,術語上稱為 TOTP(以時間為基礎的一次性密碼)。設定完驗證器 App 之後,還有一件事一定要馬上做,就是產生一組備援碼,並且存放在手機以外的地方,例如密碼管理器或列印下來收好。這一步很容易被跳過,但一旦手機遺失或損壞,沒有備援碼就等於連自己都被鎖在後台外面。

如果是多人團隊共用後台,可以依角色分級要求:管理員、編輯這類權限較高的帳號一定要開啟二階段驗證,其他權限較低的角色則可以選擇性開放,不強制。整體來說,只要是持有後台存取權的帳號都該做這一招,尤其管理員或編輯權限的帳號,優先度最高。

用驗證器 App 設定 TOTP,並存好備援碼

WordPress 核心貢獻者維護的官方外掛 Two Factor,就支援這整套設定方式:先在外掛設定頁開啟驗證器 App 這個選項,畫面會出現一組 QR Code,拿手機上的驗證器 App 掃描這個 QR Code 完成綁定,接著輸入 App 上顯示的一次性驗證碼,確認綁定成功。

綁定完成之後,緊接著要做的是產生一組備援碼,並且列印出來或存進密碼管理器裡,不要存在同一支手機的備忘錄或截圖裡。原因很直接,如果驗證碼跟備援碼都存在同一支手機上,手機遺失或損壞的當下,兩個管道就一起沒了,連你自己都進不去後台。

更進一步的選項:無密碼的 Passkey 登入

如果想再往前一步,目前最新一波的做法是完全不用密碼,改用 Passkey 登入,這也是多數舊教學文章都還沒提到的角度。Passkey 走的是 WebAuthn 與 FIDO2 這套公開規格,登入時不再輸入密碼,而是改用手機或裝置本身的生物辨識,例如指紋、臉部辨識,或是一支實體安全金鑰,來確認你就是本人。美國網路安全暨基礎設施安全局(CISA)把身分驗證的方式分成三大類:你知道的(密碼)、你擁有的(裝置或金鑰)、你本身具備的(生物特徵),Passkey 剛好結合了後面兩類,從根本上讓密碼外流這件事失去意義,因為根本沒有密碼可以外流,自然也沒有密碼能被偷走或猜中。CISA 也曾公開點名,FIDO 與 WebAuthn 這類抗釣魚的驗證方式,是目前建議的最高優先選項。

不過這裡要誠實交代現況,WordPress 核心目前仍未原生支援 Passkey,得額外裝外掛才能用,這點跟前面提到核心已經有官方維護的 Two Factor 外掛的情況不太一樣,Passkey 目前還是站在生態系比較外圍、持續發展中的做法。這個選項比較適合想走在前面,而且團隊裝置本身就支援生物辨識的網站優先嘗試,對多數網站來說,現階段還不是非做不可的必要項目。驗證關卡顧好了,最後還有一段路要走,就是從網路層直接把可疑的來源整個擋下來。

招式五:鎖定可疑來源,把防護延伸到伺服器與網路層

最後一招是把防護延伸到伺服器與網路層,直接鎖定可疑來源,這也是五招裡技術門檻最高的一步,因為牽涉到伺服器存取權限,或是 CDN、WAF 帳號的設定操作,同時也最容易做過頭,不小心誤傷正常訪客。

先講好處,這招能把攻擊請求擋在 WordPress 之外,甚至擋在伺服器之外,不會消耗到網站本身的運算資源。再講風險,共用辦公室或行動網路的使用者,常常會共用同一個對外 IP,如果 IP 層級的封鎖規則設得太嚴,可能連累到剛好用同一個 IP 出口的正常訪客;地區封鎖也可能誤擋到出差在外,或是使用 VPN 連線的合法使用者。OWASP 的官方建議也提醒,IP 層級的防護要搭配風險分級回應一起使用,不能只靠單純封鎖了事,因為攻擊者本來就常用代理伺服器或住宅 IP 分散攻擊來源,單靠封鎖特定 IP 段,效果有限。

這招最適合已經在用 Cloudflare 之類 CDN、WAF 服務,或是有能力直接操作伺服器的網站。如果網站的合法訪客高度集中在特定地區,在其他地區幾乎沒有真實流量,地區限制的效益會特別明顯。但不管用哪種做法,設定前務必先把自己管理者所在的 IP 或地區排除在封鎖名單之外,避免規則一上線,自己反而先被鎖在後台外面。

用 fail2ban 依登入紀錄自動封鎖可疑來源

具體到設定邏輯,fail2ban 的做法分成幾個步驟:先定義要監控哪一個登入紀錄檔案,接著設定要比對的登入失敗關鍵字樣式,再設定兩個關鍵參數:同一個來源失敗幾次觸發封鎖、封鎖時間要多久。條件符合之後,fail2ban 會自動在伺服器的防火牆層加上一條規則,把這個來源 IP 擋下來,時間一到再自動解除封鎖,不需要人工介入。

這段設定延續招式二提到的伺服器層技術,但重點不太一樣。招式二講的是限制嘗試的頻率,這裡講的是直接把符合攻擊模式的來源整個鎖起來,兩者其實可以並存,一個管試太快,一個管這個來源已經被認定有問題,疊在一起用會更完整。

用 CDN/WAF,依國家或 IP 範圍限制存取後台

如果網站已經掛了 Cloudflare 這類服務,可以直接針對後台路徑設定地區或 IP 範圍限制,而不是整個網站都套用同一條規則。做法是把兩個條件用「且」組合成一條規則。一個條件是請求路徑等於 /wp-admin 或 /wp-login.php,另一個條件是來源的國家或網路來源範圍,Cloudflare 官方文件提供的地區封鎖語法,就是用類似來源國家等於某個國家代碼這種條件寫成規則;搭配路徑條件之後,只有同時符合這兩個條件的請求才會被擋下來,其餘訪客正常瀏覽網站文章、看其他頁面,完全不受影響。

用路徑是後台且來源在封鎖名單兩個條件組合規則,只擋後台登入請求,讀者瀏覽文章不受影響
把「路徑是後台」和「來源在封鎖名單」用「且」組合成規則,只有同時符合才封鎖,讀者瀏覽公開文章完全不受影響(資料來源:Cloudflare)。

這樣做的好處是範圍精準,只鎖後台入口,不動到公開內容,不會因為封鎖規則設得太粗,不小心連正常讀者都擋在門外。跟前面提醒的一樣,不管是用地區條件還是 IP 範圍條件,設定前都要先把管理者自己所在的地區或 IP 排除在封鎖名單之外,免得規則生效之後,第一個被擋在外面的人是自己。

把這五招都做完,不是因為其中哪一招特別厲害,而是因為每一招都只補上一個破口,疊在一起,才真的讓「密碼夠不夠複雜」不再是攻擊者唯一能打的主意。密碼再怎麼設,終究只是登入保護裡的其中一道關卡,不是全部。

像 Passkey 這種無密碼登入的方向,正在把整個登入保護的重點,從怎麼守住一組密碼,慢慢轉向怎麼讓密碼這件事本身變得不重要。這五招現在都已經做得到,接下來要做的,只是持續跟上這個方向,把後台的每一道門都顧好。

資料來源
  1. How effective is multifactor authentication at deterring cyberattacks? — Microsoft
  2. Brute Force Amplification Attacks Against WordPress XMLRPC — Sucuri
  3. A Look at the New WordPress Brute Force Amplification Attack — Cloudflare
  4. Credential Stuffing Prevention Cheat Sheet — OWASP
  5. How and Why You Should Limit Login Attempts in WordPress — WPBeginner
  6. Protect your login Rate Limiting Template — Cloudflare
  7. SP 800-63B:Digital Identity Guidelines - Authentication and Authenticator Management — NIST
  8. Implementing Phishing-Resistant MFA — CISA