在程序開發中sql注入是一個大家常常會要考慮到的問題,下面我來解析一下常見的sql防注入代碼,有需要的朋友可參考參考.
1、PHP提交數據過濾的基本原則
1)提交變量進數據庫時,我們必須使用addslashes()進行過濾,像我們的注入問題,一個addslashes()也就搞定了,其實在涉及到變量取值時,intval()函數對字符串的過濾也是個不錯的選擇.
2)在PHP.ini中開啟magic_quotes_gpc和magic_quotes_runtime,magic_quotes_gpc可以把get,post,cookIE裡的引號變為斜槓。magic_quotes_runtime對於進出數據庫的數據可以起到格式話的作用,其實,早在以前注入很瘋狂時,這個參數就很流行了,代碼如下:
- <?PHP
- if ( isset($_POST["f_login"] ) )
- {
- // 連接數據庫...
- // ...代碼略...
- // 檢查用戶是否存在
- $t_strUname = $_POST["f_uname"];
- $t_strPwd = $_POST["f_pwd"];
- $t_strSQL = "SELECT * FROM tbl_users WHERE username='$t_strUname' AND passWord = '$t_strPwd' LIMIT 0,1";
- if ( $t_hRes = MySQL_query($t_strSQL) )
- {
- // 成功查詢之後的處理. 略...
- } //開源代碼PHPfensi.com
- }
- ?>
- <Html><head><title>sample test</title></head>
- <body>
- <form method=post action="">
- Username: <input type="text" name="f_uname" size=30><br>
- PassWord: <input type=text name="f_pwd" size=30><br>
- <input type="submit" name="f_login" value="登錄">
- </form>
- </body>
3)在使用系統函數時,必須使用escapeshellarg(),escapeshellcmd()參數去過濾,這樣你也就可以放心的使用系統函數.
4)對於跨站,strip_tags(),htmlspecialchars()兩個參數都不錯,對於用戶提交的的帶有Html和PHP的標記都將進行轉換。比如尖括號"<"就將轉化為 "<"這樣無害的字符。代碼如下:
$new = Htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);strip_tags($text,);
5)對於相關函數的過濾,就像先前的include(),unlink,fopen()等等,只要你把你所要執行操作的變量指定好或者對相關字符過濾嚴密,我想這樣也就無懈可擊了.
2、PHP簡單的數據過濾
1)入庫: trim($str),addslashes($str)
2)出庫: stripslashes($str)
3)顯示: Htmlspecialchars(nl2br($str))
一、 注入式攻擊的類型
可能存在許多不同類型的攻擊動機,但是乍看上去,似乎存在更多的類型。這是非常真實的-如果惡意用戶發現了一個能夠執行多個查詢的辦法的話。本文後面,我們會對此作詳細討論。
如果你的腳本正在執行一個SELECT指令,那麼,攻擊者可以強迫顯示一個表格中的每一行記錄-通過把一個例如"1=1"這樣的條件注入到WHERE子句中,如下所示,其中,注入部分以粗體顯示,代碼如下:
SELECT * FROM wines WHERE varIEty = 'lagrein' OR 1=1;'正如我們在前面所討論的,這本身可能是很有用的信息,因為它揭示了該表格的一般結構(這是一條普通的記錄所不能實現的),以及潛在地顯示包含機密信息的記錄。
一條更新指令潛在地具有更直接的威脅,通過把其它屬性放到SET子句中,一名攻擊者可以修改當前被更新的記錄中的任何字段,例如下面的例子,其中,注入部分以粗體顯示,代碼如下:
UPDATE wines SET type='red','vintage'='9999' WHERE varIEty = 'lagrein'
通過把一個例如1=1這樣的恆真條件添加到一條更新指令的WHERE子句中,這種修改范圍可以擴展到每一條記錄,例如下面的例子,其中,注入部分以粗體顯示,代碼如下:
UPDATE wines SET type='red','vintage'='9999 WHERE varIEty = 'lagrein' OR 1=1;'
最危險的指令可能是DELETE-這是不難想像的,其注入技術與我們已經看到的相同-通過修改WHERE子句來擴展受影響的記錄的范圍,例如下面的例子,其中,注入部分以粗體顯示,代碼如下:
DELETE FROM wines WHERE varIEty = 'lagrein' OR 1=1;'
二、多個查詢注入
多個查詢注入將會加劇一個攻擊者可能引起的潛在的損壞-通過允許多條破壞性指令包括在一個查詢中,在使用MySQL數據庫時,攻擊者通過把一個出乎意料之外的終止符插入到查詢中即可很容易實現這一點-此時一個注入的引號(單引號或雙引號)標記期望變量的結尾,然後使用一個分號終止該指令,現在,一個另外的攻擊指令可能被添加到現在終止的原始指令的結尾,最終的破壞性查詢可能看起來如下所示"
SELECT * FROM wines WHERE varIEty = 'lagrein';
GRANT ALL ON *.* TO 'BadGuy@%' IDENTIFIED BY 'gotcha';'
這個注入將創建一個新的用戶BadGuy並賦予其網絡特權(在所有的表格上具有所有的特權);其中,還有一個"不祥"的口令被加入到這個簡單的SELECT語句中。如果你遵循我們在以前文章中的建議-嚴格限制該過程用戶的特權,那麼,這應該無法工作,因為web服務器守護程序不再擁有你撤回的GRANT特權。但是從理論上講,這樣的一個攻擊可能給予BadGuy自由權力來實現他對你的數據庫的任何操作。
下面分享一個自己寫的代碼,如下:
- function PHPsql_show($str){
- $str = stripslashes($str);
- $str = str_replace("\", "", $str);
- $str = str_replace("/", "/", $str);
- $str = str_replace(" ", " ", $str);
- $str = str_replace(",", ",", $str);
- return $str;
- }
- function PHPsql_post($str){
- $str = stripslashes($str);
- $str = str_replace("|", "|", $str);
- $str = str_replace("<", "<", $str);
- $str = str_replace(">", ">", $str);
- $str = str_replace(" ", " ", $str);
- $str = str_replace(" ", " ", $str);
- $str = str_replace("(", "(", $str);
- $str = str_replace(")", ")", $str);
- $str = str_replace("`", "`", $str);
- //$str = str_replace("'", "'", $str);
- $str = str_replace('"', """, $str);
- $str = str_replace(",", ",", $str);
- $str = str_replace("$", "$", $str);
- $str = str_replace("", "\", $str);
- $str = str_replace("/", "/", $str);
- return $str;
- }//開源代碼PHPfensi.com
- function PHPsql_replace($str){
- $str = stripslashes($str);
- $str = str_replace("'", "'", $str);
- return $str;
- }
總結一下:
* addslashes() 是強行加,
* MySQL_real_escape_string() 會判斷字符集,但是對PHP版本有要求,
* MySQL_escape_string不考慮連接的當前字符集.
dz中的防止sql注入就是用addslashes這個函數,同時在dthmlspecialchars這個函數中有進行一些替換$string = preg_replace(/&((#(d{3,5}|x[a-fA-F0-9]{4}));)/, &1,這個替換解決了注入的問題,同時也解決了中文亂碼的一些問題.