第二點才是致命傷:即使 `magic_quotes_gpc = On`,若型別錯誤(如數值欄位未驗證)同樣可注入。
<?php
if (isset($_POST['f_login'])) {
$link = mysqli_connect('localhost', 'root', '', 'test');
$uname = $_POST['f_uname'];
$pwd = $_POST['f_pwd'];
// 直接拼接,極度危險
$sql = "SELECT * FROM tbl_users WHERE username='$uname' AND password='$pwd' LIMIT 0,1";
$res = mysqli_query($link, $sql);
// ...
}
?>
<form method="post">
User: <input name="f_uname"><br>
Pass: <input name="f_pwd" type="password"><br>
<input type="submit" name="f_login" value="登入">
</form>
用戶名:admin' --
密碼:任意
→ SQL 變為:SELECT * FROM tbl_users WHERE username='admin' --' AND password='xxx'
-- 之後被註解,繞過密碼驗證
$id = (int)$_GET['id']; // 強制整數
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);
$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
$stmt = $mysqli->prepare('SELECT * FROM users WHERE username=? AND password=?');
$stmt->bind_param('ss', $uname, $pwd);
$stmt->execute();
參數與 SQL 結構分離,徹底杜絕注入。
// 數值型欄位未驗證
$id = $_GET['id']; // 攻擊者傳入:1 OR 1=1
$sql = "SELECT * FROM news WHERE id=$id"; // 無引號,magic_quotes 無效
// 結果:全表洩露
結論:永遠不要依賴 magic_quotes,PHP 5.4 已移除。