首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 登錄模塊防 SQL 注入:從原理到防禦代碼實戰

     編輯:PHP 綜合知識

經典漏洞代碼

$sql = "SELECT * FROM test 
        WHERE username = '$username' 
        AND password = '$password'";
$res = mysql_query($sql);
if (mysql_num_rows($res)) {
    header('Location: home.php');
}

注入利用示例

輸入位置惡意輸入生成 SQL原理
password***" OR 1=1 --... AND password = "***" OR 1=1 --"恆真條件繞過驗證
username***" UNION SELECT * FROM users --... WHERE username = "***" UNION SELECT * FROM users --"聯合查詢讀取其他表

根本原因

用戶輸入直接拼接進 SQL 字符串,未經轉義或參數化,導致數據與代碼邊界模糊。

防禦方案對比

1. 參數化查詢 / 預處理語句(推薦,根治)

// PDO 方式
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->prepare('SELECT * FROM test WHERE username = ? AND password = ?');
$stmt->execute([$username, $password]);
if ($stmt->fetch()) { /* 登錄成功 */ }

2. 框架 ORM/Query Builder(現代開發標配)

// ThinkPHP / Laravel / Yii 等
$user = User::where('username', $username)
            ->where('password', $password) // 實際應存儲哈希
            ->first();

3. 手動轉義(僅作為歷史項目過渡)

function clean_input($data) {
    if (is_numeric($data)) return intval($data);
    if (!get_magic_quotes_gpc()) $data = addslashes($data);
    return $data;
}

$_GET  = array_map('clean_input', $_GET);
$_POST = array_map('clean_input', $_POST);

缺點: 易漏過濾、編碼繞過、二次注入風險、不支持預處理性能優勢。

4. 另一種手動過濾寫法

function post_check($post) {
    if (!get_magic_quotes_gpc()) $post = addslashes($post);
    $post = str_replace('_', '\\_', $post);
    $post = str_replace('%', '\\%', $post);
    $post = nl2br($post);
    $post = htmlspecialchars($post);
    return $post;
}

深度防禦原則

  1. 參數化查詢:所有動態 SQL 必須使用預處理
  2. 最小權限:Web 賬號僅擁有 SELECT/INSERT/UPDATE,無 DROP/ALTER
  3. 錯誤信息隱藏:生產環境關閉 SQL 錯誤回顯
  4. WAF/防火牆:ModSecurity、云 WAF 作為第二道防線
  5. 密碼存儲:永遠不存明文,使用 password_hash() + password_verify()

現代框架中的最佳實踐

  • ThinkPHP:Db::name('user')->where('username', $username)->find() 內部參數化
  • Laravel:Eloquent ORM / Query Builder 自動參數化
  • PDO:prepare() + execute() 標準化

總結

SQL 注入本質是「數據未經處理進入代碼層」。參數化查詢 從根源分離代碼與數據,是唯一徹底解法。歷史項目若難重構,務必全局強制轉義並審計每個入口。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved