各框架對策
Laravel 資安對策 — 正式環境的加固參考
一份 Laravel 正式環境加固參考:依優先度排序的檢查清單、危險的預設值,以及從機密與設定到授權與相依套件 CVE 的各領域指引,另附自我驗證檢查清單。純防禦,不含攻擊步驟。
適用對象:任何在正式環境運行 Laravel 的人。這裡沒有攻擊步驟——這是一份加固用的可實作參考:依優先度排序的檢查清單、危險的預設值、各領域指引,以及自我驗證。想看跨框架的全貌,請見 各框架資安對策的入口。
依優先度排序的加固檢查清單
由上而下處理這張表。P0 是其餘一切的前提,P1 是最常見的事故來源,P2 是持續的維運衛生。
P0 ── 前提(最先做)
正式環境關閉除錯/把機密以權限 600 擋在公開面之外/管理 APP_KEY
P1 ── 首要事故來源
授權(Policy/Gate)/Mass Assignment 控制/相依套件 CVE/正式環境快取
P2 ── 維運衛生
工作階段/CSRF/cookie/上傳驗證/HTTPS、標頭、限流
| 優先度 | 控制項 | 具體做法(Laravel) |
|---|---|---|
| P0 | 關閉正式環境除錯 | APP_DEBUG=false/APP_ENV=production,並用 config:cache 固定。別在錯誤頁面上洩漏內部資訊 |
| P0 | 機密擋在公開面之外 | .env、備份、金鑰放在 public/ 之外,權限 600。storage/logs 不對外公開 |
| P0 | 妥善管理 APP_KEY | 加密、簽章 cookie、工作階段的基礎。從環境變數注入;外洩時輪替 |
| P1 | 明確的授權 | Policy/Gate + authorize()/can middleware,依擁有者/權限界定範圍 |
| P1 | 控制 Mass Assignment | 宣告 $fillable;避免整批指派 $request->all(),改用 validated() |
| P1 | 監控 Composer CVE | composer audit/osv-scanner;依執行版本判斷,快速修補 |
| P1 | 正式環境快取 | config:cache route:cache view:cache,讓設定可靠生效+加速 |
| P2 | 工作階段/cookie 安全 | 設定 secure http_only same_site;登入時重新產生工作階段 |
| P2 | 上傳驗證 | 驗證類型/大小,存放在 public/ 之外,不給執行權限 |
| P2 | HTTPS/標頭/限流 | 強制 HTTPS、HSTS,登入/API 加上 throttle |
1. 機密與 APP_KEY(P0)
Laravel 預設就把 .env 放在文件根目錄之外(在專案根目錄)。事故多半來自把機密放到不該放的地方。
- 絕不要把
.env、DB 匯出檔、備份或金鑰檔放在public/裡。把機密以權限 600(僅擁有者)放在應用程式根目錄之外。 - 別對外暴露
storage/或storage/logs/(日誌可能含有機密或個資)。別把.envcommit 進儲存庫。 APP_KEY是加密、簽章 URL、加密 cookie 與工作階段的基礎。從環境變數注入它,並在外洩時立即輪替(注意這會使既有的加密資料/工作階段失效)。
一般原則見 別把機密資訊放進公開目錄;真實的完整外洩案例見 .env 完整外洩的案例。
2. 正式環境設定:DEBUG、環境、快取(P0)
APP_DEBUG=false/APP_ENV=production
用快取固定設定
php artisan config:cache(+ route:cache view:cache)讓設定可靠生效並加速應用程式。注意:config:cache 之後,config/ 以外的 env() 會回傳 null,因此在應用程式中要透過 config('...') 引用值。別在正式環境暴露診斷工具
3. 授權:Broken Access Control(P1——首要來源)
最常見的正式環境事故是「已驗證但未授權」。能夠登入,不代表被允許執行該動作。
常見(危險)
- 沒有授權——「登入=可檢視/更新」
- route-model binding 抓到別的使用者的 ID
Model::create($request->all())接受每一個欄位- 像
is_admin這類權限欄位被使用者輸入指派
正確
- Policy/Gate +
authorize()/canmiddleware,每次都界定擁有者/權限範圍 - 讀取也依擁有者界定範圍(例如
where('user_id', $me)) - 用
$request->validated()(FormRequest)限制輸入 - 宣告
$fillable以擋下 Mass Assignment
見 IDOR 是什麼。關鍵在於每一條讀取/更新/刪除路徑都要做擁有者檢查。
4. 注入與輸出
Laravel 的 Eloquent/查詢建構器會以佔位符綁定值,而 Blade 預設會跳脫輸出。規則是別自己把那道安全機制關掉。
- SQL:別用字串串接把使用者輸入混進
whereRaw/DB::raw。即使需要原生 SQL,也要使用綁定(→ SQL injection 是什麼)。 - XSS:Blade
{{ }}會跳脫;{!! !!}是原始輸出。別把使用者輸入傳給{!! !!}。若一定要輸出 HTML,也要在淨化之後才做(→ XSS 是什麼)。 - 驗證:使用前,用 FormRequest/
validate()驗證類型/範圍/允許值。
5. 工作階段、CSRF、cookie(P2)
- CSRF:別全域停用 web middleware 的 CSRF 防護。表單中使用
@csrf,SPA 則做妥善的 token 處理(→ CSRF 是什麼)。 - Cookie/工作階段:在
config/session.php設定secure(HTTPS)、http_only、same_site。登入時重新產生工作階段以防止固定攻擊(Laravel 的驗證會重新產生)。 - 暴力破解:對登入套用
throttle/登入嘗試次數限制。
6. 檔案上傳與公開檔案(P2)
- 驗證 mime type、副檔名與大小,且別信任用戶端提供的檔名。
- 存放在
public/之外(例如storage/),且不給執行權限。只透過受控路徑對外提供需要公開的內容。 - 也對遞送加上授權,讓連續的直接連結無法抓到別人的檔案。
7. HTTPS、安全標頭、限流(P2)
- 強制 HTTPS(
URL::forceScheme('https')等)+ HSTS。在負載平衡器後方,使用TrustProxies讓協定被正確偵測。 - 安全標頭(X-Content-Type-Options 等;依你的資產配置設計 CSP)。用 安全標頭檢測工具 檢查自己的網站。
- 限流:對登入、API 與密碼重設套用
throttle。
8. 相依套件與版本(P1)
- 用
composer audit或 osv-scanner 監控 Composer 相依套件的 CVE,依執行版本判斷,並快速修補(→ 監控相依套件 CVE · 漏洞應變實務手冊)。 - 讓 Laravel 與 PHP 維持在受支援的版本。別留著 EOL 版本(無法修補的漏洞會不斷累積)。
驗證:你的 Laravel 真的加固了嗎?
蓋好不是終點——檢查過才算完成。以下是針對你自己網站/環境的防禦性自我檢查。
機密無法透過網址取得
/.env 與 /storage/logs/laravel.log,確認它們回傳 404(若能讀取,立即修正並輪替金鑰)。正式環境沒有除錯外洩
授權有效
Cookie/工作階段與相依套件
composer audit 是乾淨的。本站的觀點:即使預設值很強,授權與相依套件仍要靠你自己
Laravel 有許多好的預設值,但授權——誰可以做什麼——以及相依套件的新鮮度是應用程式與維運特有的,所以沒有任何框架能自動替你守。我們反覆看到的事故,與其說是精巧的攻擊,不如說是設定/維運的模式:「有驗證卻沒有擁有者檢查」「正式環境開著除錯」「機密被暴露」。所以重心在於由上而下處理上面的表格,並做那件不起眼的工作——每次讀取/更新都依擁有者界定範圍,並監控相依套件的 CVE。
接下來讀
- 入口:各框架資安對策 · Next.js 資安對策
- 機密資訊:別把機密資訊放進公開目錄 · 案例:.env 的完整外洩
- 授權/實務:IDOR 是什麼 · 漏洞應變實務手冊 · 監控相依套件 CVE
- 詞彙:SQL injection · XSS · CSRF
FAQ
Q要保護 Laravel,我該先做什麼?
三個 P0 項目:(1) 確保正式環境 APP_DEBUG=false,並用 config:cache 把設定固定下來;(2) 讓 .env 與機密檔案待在公開目錄之外,並設定嚴格權限;(3) 妥善管理 APP_KEY(它是加密、簽章 cookie 與工作階段的基礎,因此外洩時要輪替)。這些是其餘一切的前提。接著再進到授權(Policy/Gate)與 Composer 相依套件 CVE 監控。
Q帶著 APP_DEBUG=true 上線有什麼危險?
開著除錯時,錯誤頁面不只會顯示堆疊追蹤,還會顯示設定值、環境變數、連線資訊等內部資訊。攻擊者可以刻意觸發錯誤把它們抓出來。在正式環境,請設定 APP_DEBUG=false 與 APP_ENV=production,並用 config:cache 讓它固定下來。此外,別在正式環境對外暴露 Telescope 或 Debugbar 這類診斷工具。
Q為什麼 config:cache 之後 env() 會回傳 null?
config:cache 為了效能把設定編譯成單一檔案,之後在設定檔以外呼叫的 env() 會回傳 null(只讀取快取當下的 .env)。修正方式是只在 config/ 內使用 env(),並在應用程式中透過 config('...') 引用值。在正式環境,快取 config/route/view 是常態——它讓設定可靠地生效,並讓應用程式更快。
Q如何避免『只要登入就代表被允許』?
驗證(登入)和授權(該動作是否被允許)是兩回事。在 Laravel 中,實作 Policy/Gate,並使用 authorize() 或 can middleware,讓每一次讀取/更新/刪除都依擁有者或權限界定範圍。此外,透過宣告 $fillable 來控制 Mass Assignment,避免整批指派 $request->all()。少了這個,把網址裡的 ID 換掉就能碰到別人的資料(IDOR)。
Q如何管理 Composer 相依套件的漏洞?
用 composer audit 或 osv-scanner 以機器監控已知 CVE,依實際執行的版本判斷,並快速修補(依實際安裝的版本決定,而非 composer.json 的宣告)。此外,讓 Laravel 與 PHP 維持在受支援的版本,別留著 EOL 版本。相依套件的新鮮度,是比精巧攻擊更貼近現實的事故因素。