1、php提交資料過濾的基本原則
1)提交變數進資料庫時,我們必須使用addslashes()進行過濾,像我們的注入問題,一個addslashes()也就搞定了。其實在涉及到變數取值時,intval()函數對字串的過濾也是個不錯的選擇。
2)在php.ini中開啟magic_quotes_gpc和magic_quotes_runtime。magic_quotes_gpc可以把get,post,cookie裡的引號變為斜杠。magic_quotes_runtime對於進出資料庫的資料可以起到格式話的作用。其實,早在以前注入很瘋狂時,這個參數就很流行了。
代碼如下 |
複製代碼 |
<? 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) ) { // 成功查詢之後的處理. 略... } } ?> <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; } 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,這個替換解決了注入的問題,同時也解決了中文亂碼的一些問題