【代碼實現】防止SQL注入解決辦法,sql注入

來源:互聯網
上載者:User

【代碼實現】防止SQL注入解決辦法,sql注入

文章來源:PHP開發學習門戶

地址:http://www.phpthinking.com/archives/494


SQL注入是我們在程式開發過程中經常要注意的問題,屬於發生於應用程式之資料庫層的安全性漏洞,通過構建特殊的輸入作為參數傳入Web應用程式,而這些輸入大都是SQL文法裡的一些組合,通過執行SQL語句進而執行攻擊者所要的操作,其主要原因是程式沒有細緻地過濾使用者輸入的資料,致使非法資料侵入系統。
簡而言之,是在輸入的字串之中注入SQL指令,在設計不良的程式當中忽略了檢查,那麼這些注入進去的指令就會被資料庫伺服器誤認為是正常的SQL指令而運行,因此遭到破壞。

這是一個簡單的資料表:
CREATE TABLE `user` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`password` varchar(50) NOT NULL,
`age` smallint(3) NOT NULL,
`is_admin` tinyint(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES (’1′, ‘tom’, ’2313sdf’, ’10′, ’0′);
INSERT INTO `user` VALUES (’2′, ‘lucy’, ‘sdff234′, ’5′, ’0′);
INSERT INTO `user` VALUES (’3′, ‘teacher wang’, ‘salfdjlkvjaldf’, ’24′, ’1′);

 

請看下面這些sql語句:
$sql=”SELECT * from user WHERE name=’$name’ and password=’$password’;”;
情況一:
若使用者通過表單提交的資訊是:
$name = “tom’ or ’1′=’1″;
$password = “test”;
資料在未經檢驗處理的情況下,導致原本的SQL字串被解析為:
SELECT * from user WHERE name=’tom’ or ’1′=’1′ and password=’test’;
sql執行結果為:
我們在沒有輸出正確密碼的情況下,拿到了“tom”的資訊,即用“tom”的身份登入了網站。
情況二:
若使用者通過表單提交的資訊是:
$name = “‘ or name!=” and is_admin=1 or ’1′=’1″;
$password = “test”;
資料在未經檢驗處理的情況下,導致原本的SQL字串被解析為:
SELECT * from user WHERE name=” or name!=” and is_admin=1 or ’1′=’1′ and password=’test’;
sql執行結果為:
我們在沒有輸出正確使用者名稱及密碼的情況下,拿到了“teacher wang”的資訊,即用“teacher wang”的身份登入了網站。
情況三:

若使用者通過表單提交的資訊是:
$name = “‘ ; DELETE FROM user;’”;
$password = “test”;
資料在未經檢驗處理的情況下,導致原本的SQL字串被解析為:
SELECT * from user WHERE name=” ; DELETE FROM user;” and password=’test’;
sql執行結果為:
悲劇了,user表資料被清空了
如何防範SQL注入攻擊:

  • 在組合SQL字串時,先針對所傳入的參數作字元轉義
  • 如果使用PHP開發網頁程式的話,亦可開啟PHP的Magic quote功能自動將所有的網頁傳入參數,將單引號字元取代為連續2個單引號字元。
  • 如果可能應該過濾以下字元:分號“;”,兩個減號“–”,單引號“’”,注釋“/* … */”。
  • 更換危險字元。例如在PHP通過addslashes()函數保護SQL注入。
  • 限制使用者輸入的長度,限制使用者輸入的取值範圍。
  • 為當前應用建立許可權比較小的資料庫使用者,這樣不會導致資料庫管理員丟失。

 

php代碼實現:
function mysql_prepare_for_request($value, $type = “string”) {
$return = $value;
switch ($type) {
case “string” :
// 去除斜杠
if (get_magic_quotes_gpc ()) {
$return = stripslashes ( $return );
}
//配置串連有效資料庫
$con = mysql_connect ( ‘localhost’, ‘root’, ‘root’ );//填寫正確的使用者名稱,密碼
if (! $con) {
die ( ‘Could not connect: ‘ . mysql_error () );
}

$return = mysql_real_escape_string ( $return );
mysql_close ( $con );
break;
case “number” :
if (! is_numeric ( $return )) {
$return = 0;
}
break;
default :
$return = “”;
break;
}

return $return;

}

 

//情況一:使用者輸入
$name = “tom’ or ’1′=’1″;
$password = “test”;
$sql=”SELECT * from user WHERE name=’$name’ and password=’$password’;”;
echo “危險:”.$sql.”<br/>”;

//資料轉義過濾
$name = mysql_prepare_for_request ( $name, ‘string’ );
$password = mysql_prepare_for_request ( $password, ‘string’ );
$sql=”SELECT * from user WHERE name=’$name’ and password=’$password’;”;
echo “安全:”.$sql.”<br/><br/>”;
//情況二:使用者輸入
$name = “‘ or name!=” and is_admin=1 or ’1′=’1″;
$password = “test”;
$sql=”SELECT * from user WHERE name=’$name’ and password=’$password’;”;
echo “危險:”.$sql.”<br/>”;

//資料轉義過濾
$name = mysql_prepare_for_request ( $name, ‘string’ );
$password = mysql_prepare_for_request ( $password, ‘string’ );
$sql=”SELECT * from user WHERE name=’$name’ and password=’$password’;”;
echo “安全:”.$sql.”<br/><br/>”;
//情況三:使用者輸入
$name = “‘ ; DELETE FROM user;’”;
$password = “test”;
$sql=”SELECT * from user WHERE name=’$name’ and password=’$password’;”;
echo “危險:”.$sql.”<br/>”;

//資料轉義過濾
$name = mysql_prepare_for_request ( $name, ‘string’ );
$password = mysql_prepare_for_request ( $password, ‘string’ );
$sql=”SELECT * from user WHERE name=’$name’ and password=’$password’;”;
echo “安全:”.$sql.”<br/><br/>”;

 

輸出結果:

危險:SELECT * from user WHERE name=’小明’ or ’1′=’1′ and password=’test’;
安全:SELECT * from user WHERE name=’小明\’ or \’1\’=\’1′ and password=’test’;

危險:SELECT * from user WHERE name=” or name!=” and is_admin=1 or ’1′=’1′ and password=’test’;
安全:SELECT * from user WHERE name=’\’ or name!=\’\’ and is_admin=1 or \’1\’=\’1′ and password=’test’;

危險:SELECT * from user WHERE name=” ; DELETE FROM user;” and password=’test’;
安全:SELECT * from user WHERE name=’\’ ; DELETE FROM user;\” and password=’test’;

 

下載源碼      (點擊地址最下面即可)



sql防注入代碼怎使用

防不了啥. 要防SQL 注入的最好辦法,是用預存程序.
 
怎徹底防止SQL注入?

1、對,限制使用者輸入肯定有效
2、應該也可以做到,但正則不是一種高效的方法,用HtmlEncode的方法可以有效防止空格等被DBMS解釋,但注意別把編碼、解碼搞反了;預存程序是DBMS執行的一段程式,把資料操縱交給預存程序執行,而不是提交SQL語句,可以有效防止SQL注入。
3、地址欄的Sql攻擊,下面我引用了一段資料解釋,他關於機制說的較清楚,關於解決,只是從用戶端考慮的,實際上用預存程序等都可以防範。
資料:
首先,入侵者會對一個網站確定可不可以進行注入,假設一篇文章的地址為:www.naohou.cn/show.asp?id=325一般會以提交兩個地址來測試,如:
www.naohou.cn/show.asp?id=325 and 1=1
www.naohou.cn/show.asp?id=325 and 1=2
第一個地址後面加了 and 1=1,構成的SQL語句也就變為了:Select * from 表單名 where id=1 and 1=1這句話要成立就必須and前後語句都成立。那麼前面的文章地址是可以訪問的,後面的1=1也是客觀成立的,那麼第一個地址就可以正常顯示;相反1=2是顯然不成立的,關鍵就看這步了,如果提交and 1=2頁面還是正常顯示說明他並沒有將and 1=2寫入SQL語句,此站也就不存在注入漏洞;但如果提交and 1=2之後返回了錯誤頁面則說明此網站將後面的語句帶入了SQL語句並執行了,也就說明他可以進行SQL注入。(註:如果地址後面跟的是news.asp?id='1'就得變為news.asp?id=1' and '1'='1來補全引號了)
那麼,知道可以注入後入侵者可以做什麼呢?
這裡就簡單的說一下,比如提交這樣的地址:
www.naohou.cn/show.asp?id=325 and exists (select * from 表名 where 列名=資料)
根據返回的正確或錯誤頁面來判斷猜的表名和列名是否正確,具體實現時是先猜表名再猜列名。當猜出表名和列名之後還可以用ASC和MID函數來猜出各列的資料。MID函數的格式為:mid(變數名,第幾個字元開始讀取,讀取幾個字元),比如:mid(pwd,1,2)就可以從變數pwd中的第一位開始讀取兩位的字元。ASC函數的格式為:ASC("字串"),如:asc("a")就可以讀出字母a的ASCII碼了。那麼實際應用的時候就......餘下全文>>
 

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.