本類提供三層防護:全局 GPC 過濾(入口統一轉義)、類型化檢查函數(整數/字串/搜尋關鍵字)、SQL 關鍵字黑名單(二次攔截)。
<?php
// === 1. 全局 GPC 過濾(放在入口文件最前面 require_once) ===
if (@get_magic_quotes_gpc()) {
$_GET = _deepAddSlashes($_GET);
$_POST = _deepAddSlashes($_POST);
$_COOKIE = _deepAddSlashes($_COOKIE);
$_FILES = _deepAddSlashes($_FILES);
}
$_SERVER = _deepAddSlashes($_SERVER);
function _deepAddSlashes(&$val) {
if (is_array($val)) {
foreach ($val as $k => $v) $val[$k] = _deepAddSlashes($v);
} elseif (is_string($val)) {
$val = addslashes($val);
} elseif (is_numeric($val)) {
$val = intval($val);
}
return $val;
}
// === 2. 類型化驗證函數 ===
// 整數參數(ID、頁碼等)
function intCheck($val, $min = null, $max = null) {
if ($val === '' || $val === null) die('參數不能為空');
if (!ctype_digit((string)$val)) die('非法參數:非純數字');
$val = intval($val);
if ($min !== null && $val < $min) die("參數不能小於 $min");
if ($max !== null && $val > $max) die("參數不能大於 $max");
return $val;
}
// 字串參數(標題、內容等)
function strCheck($val, $maxLen = 255) {
if (injectCheck($val)) die('非法參數:疑似 SQL 注入');
$val = htmlspecialchars($val, ENT_QUOTES, 'UTF-8');
if (strlen($val) > $maxLen) die("內容過長,最多 $maxLen 字符");
return $val;
}
// 搜尋關鍵字(需保留 % _ 通配符)
function searchCheck($val) {
if (injectCheck($val)) die('非法參數');
$val = str_replace(['_', '%'], ['\_', '\%'], $val);
return htmlspecialchars($val, ENT_QUOTES, 'UTF-8');
}
// 表單提交綜合檢查
function postCheck($val, $min = 0, $max = 65535) {
$len = strlen($val);
if ($len < $min) die("最少 $min 字節");
if ($len > $max) die("最多 $max 字節");
return stripslashesDeep($val); // 還原 addslashes
}
function stripslashesDeep(&$val) {
if (is_array($val)) foreach ($val as $k => $v) $val[$k] = stripslashesDeep($v);
elseif (is_string($val)) $val = stripslashes($val);
return $val;
}
// === 3. SQL 注入特徵黑名單 ===
function injectCheck($str) {
// 僅作二次攔截,不能替代預處理!
$pattern = '/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/i';
return preg_match($pattern, $str) === 1;
}
?>
<?php
require_once 'common_filter.php';
// 列表頁:page 必須是正整數
$page = intCheck($_GET['page'] ?? 1, 1, 10000);
// 文章詳情:id 整數
$id = intCheck($_GET['id']);
// 搜尋:關鍵字保留通配符
$kw = searchCheck($_GET['kw'] ?? '');
// 發布文章:標題、內容
$title = strCheck($_POST['title'], 100);
$content = strCheck($_POST['content'], 65535);
// 入庫時使用 PDO 預處理(終極防線)
$stmt = $pdo->prepare("INSERT INTO article (title, content) VALUES (?, ?)");
$stmt->execute([$title, $content]);
?>
htmlspecialchars($str, ENT_QUOTES, 'UTF-8') 防 XSS。json_encode。escapeshellarg。injectCheck 只能攔截明顯攻擊,無法防禦編碼繞過、二次注入等。mysql_query($sql) 改為 $pdo->prepare()->execute()addslashes,改用類型化驗證函數htmlspecialcharssql_mode=STRICT_TRANS_TABLES