PHP漏洞全解(五)-SQL注入攻擊
SQL注入攻擊(SQL Injection),是攻擊者在表單中提交精心構造的sql語句,改動原來的sql語句,如果web程序沒有對提交的數據經過檢查,那么就會造成sql注入攻擊。
SQL注入攻擊的一般步驟:
1、攻擊者訪問有SQL注入漏洞的站點,尋找注入點
2、攻擊者構造注入語句,注入語句和程序中的SQL語句結合生成新的sql語句
3、新的sql語句被提交到數據庫中執行 處理
4、數據庫執行了新的SQL語句,引發SQL注入攻擊
實例
數據庫
- CREATE TABLE `postmessage` (
- `id` int(11) NOT NULL auto_increment,
- `subject` varchar(60) NOT NULL default ”,
- `name` varchar(40) NOT NULL default ”,
- `email` varchar(25) NOT NULL default ”,
- `question` mediumtext NOT NULL,
- `postdate` datetime NOT NULL default ’0000-00-00 00:00:00′,
- PRIMARY KEY (`id`)
- ) ENGINE=MyISAM DEFAULT CHARSET=gb2312 COMMENT=’運用者的留言’ AUTO_INCREMENT=69 ;
- grant all privileges on ch3.* to ‘sectop’@localhost identified by ’123456′;
- //add.php 插入留言
- //list.php 留言列表
- //show.php 顯示留言
頁面 http://www.netsos.com.cn/show.php?id=71 可能存在注入點,我們來測試
http://www.netsos.com.cn/show.php?id=71 and 1=1
返回頁面
一次查詢到記錄,一次沒有,我們來看看源碼
//show.php 12-15行
// 執行mysql查詢語句
$query = "select * from postmessage where id = ".$_GET["id"];
$result = mysql_query($query)
or die("執行ySQL查詢語句失敗:" . mysql_error());
參數id傳遞進來后,和前面的字符串結合的sql語句放入數據庫執行 查詢
提交 and 1=1,語句變成select * from postmessage where id = 71 and 1=1 這語句前值后值都為真,and以后也為真,返回查詢到的數據
提交 and 1=2,語句變成select * from postmessage where id = 71 and 1=2 這語句前值為真,后值為假,and以后為假,查詢不到任何數據
正常的SQL查詢,經過我們構造的語句之后,形成了SQL注入攻擊。通過這個注入點,我們還可以進一步拿到權限,比如說運用 union讀取管理密碼,讀取數據庫信息,或者用mysql的load_file,into outfile等函數進一步滲透。
防范方法
整型參數:
運用 intval函數將數據轉換成整數
函數原型
int intval(mixed var, int base)
var是要轉換成整形的變量
base,可選,是基礎數,默認是10
浮點型參數:
運用 floatval或doubleval函數分別轉換單精度和雙精度浮點型參數
函數原型
int floatval(mixed var)
var是要轉換的變量
int doubleval(mixed var)
var是要轉換的變量
字符型參數:
運用 addslashes函數來將單引號“’”轉換成“\’”,雙引號“"”轉換成“\"”,反斜杠“\”轉換成“\\”,NULL字符加上反斜杠“\”
函數原型
string addslashes (string str)
str是要檢查的字符串
那么剛才出現的代碼漏洞,我們可以這樣修補
// 執行mysql查詢語句
$query = "select * from postmessage where id = ".intval($_GET["id"]);
$result = mysql_query($query)
or die("執行ySQL查詢語句失敗:" . mysql_error());
如果是字符型,先判斷magic_quotes_gpc能無法 為On,當不為On的時候運用 addslashes轉義特殊字符
- if(get_magic_quotes_gpc())
- {
- $var = $_GET["var"];
- }
- else
- {
- $var = addslashes($_GET["var"]);
- }
再次測試,漏洞已經修補