WordPress 接案者一定要懂的 CSRF 與權限檢查

如果你有在使用 AI 開發 WordPress 外掛,並且要設計一些自訂的後台管理介面時,一定遇過資料送出時無法正確儲存,或是儲存後被導向到奇怪的頁面。

根據我的經驗,這十之八九是 Nonce 的問題,AI 在處理 Nonce 這一塊常常會出錯,為了讓 AI 更好地理解該怎麼處理 Nonce,這篇文章就來分享 Nonce 的作用,以及如何讓 AI 不要再犯這種錯。

Nonce 是為了擋 CSRF 而生的

所謂的 Nonce,最主要的功能是要防止跨站請求偽造(也就是俗稱的 CSRF)。

CSRF 主要的攻擊方式,是攻擊者誘導已經登入受害者的瀏覽器,自動發送請求到你的網站,也就是說,攻擊者不需要入侵你的網站,只要你的瀏覽器在登入狀態下點擊了惡意網址,攻擊就會開始。

舉個例子:

  1. 站長登入了某個 WordPress 網站的後台沒登出,繼續開著分頁
  2. 站長切換到另一個由惡意攻擊者準備好的頁面,這個惡意頁面藏了一段惡意程式
  3. 程式裡面的連結會指向站長 WordPress 後台
  4. 瀏覽器在送出這個請求時,會自動帶上站長已經登入的 Cookie(因為原本分頁沒關)
  5. 站長踩到這個惡意網址、讀到那段 HTML 裡埋的 JavaScript 與 WordPress 後台執行參數,網站就會受到影響

另一種方式,是用 JavaScript 自動提交表單來攻擊。只要你的分頁沒關、進入惡意網址,而惡意網址又知道你的後台位置,它就能進行跨站請求偽造以達成攻擊,而 WordPress 的後台網址你知、我知、獨眼龍也知,因此非常容易用釣魚的手法誘使受害者點擊。

Nonce 怎麼擋住 CSRF

為了解決這個問題,WordPress 設計了 Nonce 機制,用來確保每一個請求都是從自己的網站送出的。Nonce 的全名是 Number Used Once,也就是只用一次的數字,但這個名字其實有點誤導,因為它預設的有效期限是 12 到 24 個小時。

它的運作原理適當使用者載入網站的某個介面(後台、設定頁、表單頁)時,伺服器會用 wp_create_nonce() 產生一段 Token,這段 Token 會被放進後台介面的隱藏欄位,或塞進 JS 的變數裡。

當使用者按下按鈕觸發操作時,前端會把這個 Nonce 跟其他資料一起送回伺服器。伺服器收到後,用 wp_verify_nonce() 比對 Nonce 是否相符。如果通過,就代表這個請求是從我自己的網站介面送出的。

它能擋住 CSRF 是因為計算 Nonce 的時候帶了 Secret Key(存在 wp-config.php 裡的加密金鑰),這個金鑰只有你自己的網站知道,惡意網址沒辦法產生出能通過驗證的 Nonce,攻擊者無法取得正確的 Nonce 來偽造請求,CSRF 就能擋下來了。

但光有 Nonce 還不夠

WordPress 的前台與後台雖然都有 Nonce,但光靠 Nonce 其實是不夠的。

關鍵點在假設今天攻擊者註冊成為你的網站會員(例如訂閱者),當他登入後打開外掛的某個前台頁面,伺服器就會為他產生一個合法的 Nonce,這時他拿到這個 Nonce,就可以放到自己準備的請求中,藉此發送一個「合法的」跨站偽造請求。

所以,除了 Nonce 之外,我們還要檢查身分權限,確保目前的使用者真的有權限執行當下的行為。

基本原則是:如果要防止 CSRF,同時也防止低權限使用者拿到 Nonce 來偷襲,記得除了驗證 Nonce 之外,還必須檢查使用者權限,尤其是當後台操作會修改資料庫,或查詢敏感機密資料時,都要做到 Nonce 與使用者權限的雙重檢查

一張票進 VIP 廳?想像電影院的剪票口

換個方式理解這件事——想像你去看電影:

  1. 你在訂票網站訂了「賭俠 19:30,第 5 排第 3 座」,拿到一張票
  2. 進電影院門口,剪票員看你的票,確認「你有資格進賭俠 19:30 那個放映廳」,這就是 Nonce 驗證:「你帶對票了嗎?」
  3. 但剪票員不會檢查你是 VIP 還是學生,身分是另一回事

回到 WordPress:

電影院WordPress 對應API防什麼
noncewp_create_nonce() / wp_verify_nonce() / check_ajax_referer()CSRF:證明請求來自合法介面
身分驗證capabilitycurrent_user_can( 'capability' )權限提升:證明操作者有對應角色

兩道防線缺一不可:

  • check_ajax_referer() 確認「這張票是我們電影院的票」——擋外部誘導攻擊
  • current_user_can() 確認「拿票的人有 VIP 廳的資格」——擋內部低權限帳號偷襲

AI 寫 Nonce 最常犯的錯:名稱對不上

一個 AI 常犯的問題是它在埋入表單頁面的 Nonce 名稱,跟後端驗證時用的名稱常常不一致,一個頁面中可能同時有多個表單操作行為,AI 很容易搞混特定的 Nonce 應該用在哪一個動作上。

比較好的做法是:

  1. 請 AI 先規劃每一個表單的 Nonce 該用什麼名稱
  2. 請 AI 把這些名稱整理成表格
  3. 讓 AI 在進行資料操作與驗證時,對照表格使用正確的 Nonce,避免名稱錯亂

簡單舉例,可以請 AI 先列出像這樣的對照表再開始寫程式碼:

表單行為Nonce action 名稱Nonce 欄位名驗證點
儲存設定dwp_save_settingsdwp_settings_nonceadmin_post_dwp_save_settings
刪除文章dwp_delete_postdwp_delete_noncewp_ajax_dwp_delete_post
匯入 CSVdwp_import_csvdwp_import_nonceadmin_post_dwp_import_csv

把這張表給 AI 當「規格」,再讓它寫程式碼就能大幅降低 Nonce 名稱錯亂的機率。

接案者的自我檢查清單

接到的案子要稽核安全,或自己用 AI 寫的時候要避雷,可以照這個清單檢查每一個 wp_ajax_* 或表單 hook:

  1. 這個動作會改資料庫嗎?(刪除、修改、新增)會的話必檢查下面三項
  2. check_ajax_referer()wp_verify_nonce() 嗎? 沒有,CSRF 就沒擋
  3. current_user_can( '某個合理的 capability' ) 嗎? 沒有,訂閱者就能偷襲
  4. 輸入有 intval() / sanitize_text_field() 等過濾嗎? 沒有就是 SQL injection 或 XSS 的入口

四個都做到,才算「我加了 nonce 啊」這句話真的成立。

如果想看完整的 WordPress 外掛安全稽核流程,可以接著看逆向走一次 WordPress 外掛漏洞,學會資安稽核的攻擊者思維;如果是 XSS 那一塊還沒讀過,WordPress XSS 攻擊:漏洞成因與真實 CVE 攻擊案例會把另一條漏洞線補上。整站層級的弱密碼、檔案竄改、XML-RPC 防護則整理在WordPress 安全防護實戰這篇。

用 AI 寫 WordPress 外掛踩到坑想找人聊聊?

如果你正在用 AI 開發 WordPress 外掛或客製化網站,但每次遇到 Nonce、權限、漏洞這類安全問題就卡住,或者寫出來的程式碼自己也不確定有沒有藏雷——歡迎來聊聊。

我提供兩種服務:

  • WordPress 客製化開發:直接把案子交給我做,從架構規劃到安全稽核一條龍,適合手上有客戶但人力不足的工作室,或是專案技術門檻高、不想自己踩坑的接案者。
  • WordPress AI 開發顧問諮詢:把我累積 11 年的 WordPress 開發經驗變成你的方法論,涵蓋流程盤點、客製化框架、漏洞情報監控,適合想導入 AI 但不知道怎麼控品質的接案團隊。

不取代你開發,而是讓你的 AI 開發流程不會踩到因為 Nonce 而造成的卡關。

歡迎到 WordPress AI 開發顧問服務 看完整方案,或與我聯絡聊聊你的案子。

目錄

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

Picture of 賴俊吾 / Oberon Lai
賴俊吾 / Oberon Lai

現為全職 WordPress 工程師,網站開發經歷 11 年,專攻前端工程與 WordPress 佈景主題、外掛客製化開發

訂閱電子報

Hi,我是 Oberon,我會固定在每週五早上發送接案心得以及與 WordPress 相關的電子報,同時也會分享一些實用的開發知識,讓你在 WordPress 的接案路上不孤單!

專注於分享 WordPress 開發、接案技巧、專案管理等自由工作者必備知識與心得

© 2025 想點創意科技有限公司

想點創意科技有限公司 | 統一編號 90516823
Designed by Hend Design | 隱私權政策

訂閱電子報

Hi,我是 Oberon,我會固定在每週五早上發送接案心得以及與 WordPress 相關的電子報,同時也會分享一些實用的開發知識,讓你在 WordPress 的接案路上不孤單!