/* 或 #(MySQL 註釋),如 id=1607 and 1=1/*。ORDER BY n 遞增直到報錯,得知欄位數。UNION SELECT username,password,1,2,3 FROM user 將管理帳號密碼顯示於前端。mysql_real_escape_string()(PHP)或驅動程式提供的參數化查詢(Prepared Statement),addslashes() 為最後備援。當連線字符集為 GBK 等多位元組編碼時,%df' 經 addslashes 轉義變 %df\'(\ 為 %5c)。MySQL 以 GBK 解碼時,%df%5c 被視為一個雙位元組字元「縗」,單引號得以「倖存」並閉合 SQL 語句。
$conn = mysql_connect("localhost","root","pwd");
mysql_query("SET NAMES 'GBK'");
$user = mysql_escape_string($_GET['user']);
$pass = mysql_escape_string($_GET['pass']);
$sql = "SELECT * FROM cms_user WHERE username='$user' AND password='$pass'";
攻擊 URL:login.php?user=%df' OR 1=1 LIMIT 1,1%23&pass=
實際 SQL:SELECT * FROM cms_user WHERE username='縗' OR 1=1 LIMIT 1,1#' AND password=''
連線建立並設定字符集後,強制客戶端字符集為二進制:
mysql_query("SET character_set_client=binary");
或改用 mysqli/PDO 參數化查詢,完全避開字元編碼陷阱。