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

PHP SQL 注入實戰演示與防禦:從萬能密碼到 PDO 預處理徹底修復

     編輯:PHP 相關知識

漏洞代碼還原

<?php
$username = $_POST['username'];
$password = $_POST['password'];

$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$res = mysql_query($sql); // 假設舊版 mysql_* 函數

if (mysql_num_rows($res)) {
    header('Location: home.php');
} else {
    die('登錄失敗');
}

攻擊 Payload 構造

輸入字段Payload生成 SQL原理
password`' OR '1'='1``... AND password = '' OR '1'='1'`條件恒真繞過驗證
username`admin'--``... WHERE username = 'admin'--' AND ...``--` 註釋掉後續條件
username`' UNION SELECT 1,2,3--`聯合查詢讀取其他表數據需列數匹配、類型兼容

為什麼過濾/轉義不可靠?

  • `addslashes()` 繞過:多字節編碼 (GBK) 吃掉反斜線。
  • `mysql_real_escape_string()` 需正確設置連接字符集,否則失效。
  • 黑名單過濾 (select, union 等) 極易繞過 (大小寫、編碼、註釋)。

根治方案:PDO 預處理語句

<?php
$dsn = 'mysql:host=127.0.0.1;dbname=app;charset=utf8mb4';
$pdo = new PDO($dsn, 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false, // 關鍵:使用真實預處理
]);

$stmt = $pdo->prepare('SELECT * FROM users WHERE username = ? AND password = ?');
$stmt->execute([$_POST['username'], $_POST['password']]); // 密碼應為哈希值
$user = $stmt->fetch();

if ($user) {
    // 驗證密碼哈希
    if (password_verify($_POST['password'], $user['password_hash'])) {
        // 登錄成功
    }
}

深度防禦清單

  1. 最小權限:數據庫賬號僅擁有必要表的 SELECT/INSERT/UPDATE,無 DROP/ALTER。
  2. 錯誤信息不外露:生產環境 `display_errors=Off`,錯誤寫日志不顯示頁面。
  3. WAF/IDS:部署 ModSecurity 或雲 WAF 攔截明顯攻擊特徵。
  4. 代碼審計:引入 PHPStan、Psalm 靜態分析,CI 集成 SQL 注入掃描工具 (sqlmap 自動化測試)。
  5. ORM/Query Builder:優先使用 Eloquent、Doctrine、Medoo 等構建查詢,避免手寫 SQL。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved