摒棄「安不安全」的模糊說法,精準定位 HTTP 封包物理位置與記憶體斷言機制。
狀態語意:冪等讀取。 向伺服器索取資料,不改變伺服器狀態。
?keyword=apple&page=2)。<!-- HTML 寫法 --> <form method="GET" action="search.php"> <input type="text" name="keyword"> </form> // PHP 接收法 $keyword = $_GET['keyword'];
狀態語意:狀態突變 (Mutation)。 執行會改變伺服器狀態的動作。
<!-- HTML 寫法 --> <form method="POST" action="login.php"> <input type="password" name="pwd"> </form> // PHP 接收法 $password = $_POST['pwd'];
客戶端驗證 (Client-side / JS & HTML5):
使用 HTML 的 required、minlength 或是 JavaScript 的 onsubmit 檢查。這只是為了 UX (使用者體驗),減少伺服器不必要的運算。但它是「可被繞過的假性防禦」。駭客可以輕易禁用瀏覽器 JS,或使用 cURL / Postman 直接構造 HTTP 封包攻擊伺服器。
伺服器端驗證 (Server-side / PHP):
系統的 「絕對物理防禦邊界」。無論前端怎麼檢查,後端必須假設「所有接收到的數據都是惡意的」,重新進行變量斷言。
防禦「必填欄位缺失」。檢查變數是否不存在、為空字串 ""、0 或 null。
if (empty($_POST['username'])) { die("錯誤:使用者名稱不能為空"); }
防禦「緩衝區溢位」或「資料庫截斷」。確保字串長度在合理範圍內。
$pwd = $_POST['password']; if (strlen($pwd) < 8) { die("錯誤:密碼長度過短"); }
防禦「SQL 注入」的基礎。確保應該是數字的變數 (如 ID、年齡) 絕對不包含惡意字元。
if (!is_numeric($_POST['age'])) { die("錯誤:年齡必須是純數字"); }
最高級別的權限防禦。只允許用戶輸入你預先定義好的安全值,捨棄未知的惡意輸入。
$allowed = ['user', 'admin']; if (!in_array($_POST['role'], $allowed)) { die("錯誤:非法的權限角色"); }
strpos() 用於尋找子字串的索引位置。致命漏洞:如果目標字元在字串的第一個位置 (Index 0),PHP 會回傳 0。但在鬆散比對中,0 == false 成立,會導致邏輯誤判。因此必須使用嚴格型別比對 === 或 !==。
$email = "@attack.com"; // @ 在 index 0 // 錯誤寫法 (會誤以為找不到 @): if (strpos($email, '@') == false) { die("無效信箱"); } // 正確寫法 (嚴格比對型別與值): if (strpos($email, '@') === false) { die("無效信箱"); }
物理機制: HTTP 協定天生「失憶 (無狀態)」,伺服器無法分辨連續兩次請求是否來自同一人。setcookie() 是一道透過 HTTP Response Header 發送的指令,強迫客戶端瀏覽器在本地硬碟存下一段「鍵值對 (Key-Value)」。未來瀏覽器對該網域發送的每一個請求,都會自動挾帶此 Cookie。
role=user 改為 role=admin)。機密資料絕對不可放入。HttpOnly 標籤,惡意 JavaScript 可以輕易讀取並盜走用戶的登入 Cookie。嘗試在左側表單輸入不同數據,選擇傳輸協定 (GET/POST) 並點擊「發送」。觀察中間的「HTTP 網路封包」差異,並點擊右側「Step」觀測伺服器如何進行斷言攔截。