所有非程式碼直接撰寫的資料皆為「受汙染」:
$_GET、$_POST、$_REQUEST$_COOKIE、$_SESSION(可被竄改)$username = $_POST['username']; // 汙染!
$safe = cleanInput($username); // 淨化後才可用
function cleanInput($input) {
$clean = strtolower($input);
$clean = preg_replace('/[^a-z]/', '', $clean); // 僅保留字母
return substr($clean, 0, 12); // 限制長度
}
register_globals = Off(PHP 5.4+ 已移除)magic_quotes_gpc = Off(PHP 5.4+ 已移除)display_errors = Off(生產環境)error_reporting = E_ALL & ~E_NOTICE保持程式碼清晰、單一職責、避免過度壓縮邏輯:
// 難以審計
$input = isset($_POST['u']) ? $_POST['u'] : '';
// 易審計
$input = '';
if (isset($_POST['username'])) {
$input = $_POST['username'];
}
同一風險點**多層防護**:
$sql = "SELECT * FROM users WHERE user='{$_POST['user']}' AND pass='{$_POST['pass']}'";
輸入 ' OR '1'='1 繞過驗證。
$stmt = $pdo->prepare("SELECT * FROM users WHERE user=? AND pass=?");
$stmt->execute([$_POST['user'], $_POST['pass']]);
$pid = $_GET['pid'];
if (!preg_match('/^[0-9]{1,5}$/', $pid)) {
die('非法參數');
}
// 縱深:資料庫層再次 escape
$sql = "SELECT * FROM page WHERE pid='" . $pdo->quote($pid) . "'";
// 前端限制
// 後端截斷
$name = substr($_POST['name'], 0, 40);
// 清除十六進位注入嘗試
$name = preg_replace('/\\\\x[0-9a-fA-F]{1,3}/', '', $name);
// 輸出到 HTML 內容
echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
// 輸出到 JavaScript
echo json_encode($userInput);
// 輸出到 URL
echo urlencode($userInput);
// 允許有限標籤
echo strip_tags($input, '');
隱藏欄位 <input type="hidden" name="table" value="users"> 可被工具竄改。
**對策**:伺服端**不可信任**隱藏欄位,權限控制靠 Session/Token。
<?php
session_start();
$token = md5(uniqid(rand(), true));
$_SESSION['csrf_token'] = $token;
?>
<?php
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die('CSRF 驗證失敗');
}
// 處理表單...
?>
| 風險 | 核心對策 | 縱深措施 |
|---|---|---|
| SQL 注入 | 預備語句 | 輸入白名單、最小權限 DB 帳號 |
| XSS | 輸出語境編碼 | CSP 標頭、HttpOnly Cookie |
| CSRF | 同步 Token 驗證 | SameSite Cookie、Referer 檢查 |
| 參數竄改 | 白名單驗證 | 簽名/加密關鍵參數 |
| 檔案上傳 | 型別/大小/副檔名驗證 | 儲存非網頁目錄、重新命名、掃毒 |