在 SQL 插入式攻擊 中,使用者通過操縱表單或 GET 查詢字串,將資訊添加到資料庫查詢中。例如,假設有一個簡單的登入資料庫。這個資料庫中的每個記錄都有一個使用者名稱欄位和一個密碼欄位。構建一個登入表單,讓使用者能夠登入。
清單 5. 簡單的登入表單
<html> <head> <title>Login</title> </head> <body> <form action="verify.php" method="post"> <p><label for='user'>Username</label> <input type='text' name='user' id='user'/> </p> <p><label for='pw'>Password</label> <input type='password' name='pw' id='pw'/> </p> <p><input type='submit' value='login'/></p> </form> </body> </html>
|
這個表單接受使用者輸入的使用者名稱和密碼,並將使用者輸入提交給名為 verify.php 的檔案。在這個檔案中,PHP 處理來自登入表單的資料,如下所示:
清單 6. 不安全的 PHP 表單處理代碼
<?php $okay = 0; $username = $_POST['user']; $pw = $_POST['pw'];$sql = "select count(*) as ctr from users where username='".$username."' and password='". $pw."' limit 1"; $result = mysql_query($sql); while ($data = mysql_fetch_object($result)){ if ($data->ctr == 1){ //they're okay to enter the application! $okay = 1; } } if ($okay){ $_SESSION['loginokay'] = true; header("index.php"); }else{ header("login.php"); } ?>
|
這段代碼看起來沒問題,對嗎?世 界各地成百(甚至成千)的 PHP/MySQL 網站都在使用這樣的代碼。它錯在哪裡?好,記住 “不能信任使用者輸入”。這裡沒有對來自使用者的任何資訊進行轉義,因此使應用程式容易受到攻擊。具體來說,可能會出現任何類型的 SQL 插入式攻擊。
例如,如果使用者輸入 foo 作為使用者名稱,輸入 ' or '1'='1 作為密碼,那麼實際上會將以下字串傳遞給 PHP,然後將查詢傳遞給 MySQL:
$sql = "select count(*) as ctr from users where username='foo' and password='' or '1'='1' limit 1"; |
這個查詢總是返回計數值 1,因此 PHP 會允許進行訪問。通過在密碼字串的末章節附註入某些惡意 SQL,駭客就能裝扮成合法的使用者。
解決這個問題的辦法是,將 PHP 的內建 mysql_real_escape_string() 函數用作任何使用者輸入的封裝器。這個函數對字串中的字元進行轉義,使字串不可能傳遞撇號等特殊字元並讓 MySQL 根據特殊字元進行操作。清單 7 展示了帶轉義處理的代碼。
清單 7. 安全的 PHP 表單處理代碼
<?php $okay = 0; $username = $_POST['user']; $pw = $_POST['pw'];$sql = "select count(*) as ctr from users where username='".mysql_real_escape_string($username)."' and password='". mysql_real_escape_string($pw)."' limit 1"; $result = mysql_query($sql); while ($data = mysql_fetch_object($result)){ if ($data->ctr == 1){ //they're okay to enter the application! $okay = 1; } } if ($okay){ $_SESSION['loginokay'] = true; header("index.php"); }else{ header("login.php"); } ?>
|
使用 mysql_real_escape_string() 作為使用者輸入的封裝器,就可以避免使用者輸入中的任何惡意 SQL 注入。如果使用者嘗試通過 SQL 注入傳遞畸形的密碼,那麼會將以下查詢傳遞給資料庫:
select count(*) as ctr from users where \ username='foo' and password='\' or \'1\'=\'1' limit 1" |
資料庫中沒有任何東西與這樣的密碼匹配。僅僅採用一個簡單的步驟,就堵住了 Web 應用程式中的一個大漏洞。這裡得出的經驗是,總是應該對 SQL 查詢的使用者輸入進行轉義。
為了您的安全,請只開啟來源可靠的網址
來自: http://hi.baidu.com/luzheng22/blog/item/af49aca48ea018f19052eeea.html