2012-03-13 54 views
-1

我正在嘗試使用PHP和MySQL,但現在我發現了一個我想使用的PHP代碼,但它對於SQL注入而言很脆弱。有誰知道什麼是注入,什麼代碼可以修復它?這個PHP代碼究竟是什麼問題?

<? 
     // both the username and password must be specified 
     if(!isset($_GET["username"]) || !isset($_GET["password"])) { 
       print "NO username and/or password"; 
       die; 
     } 
     $username = $_GET["username"]; 
     $password = $_GET["password"]; 

     // prepare database connection 
     mysql_connect("host", "user", "password"); 
     mysql_select_db("dbase"); 

     // validate the specified username 
     $res = mysql_query("SELECT id FROM users WHERE username = '$username'"); 

     if(!$res || !($row = mysql_fetch_row($res))) { 
       print "Unknown username"; 
       die; 
     } 
     // validate the password 
     $res = mysql_query("SELECT password FROM users WHERE id = ".$row[0]); 
     if(!$res || !($row = mysql_fetch_row($res))) { 
       print "Illegal userid record"; 
       die; 
     } 
     if($password != $row[0]) { 
       print "Invalid password"; 
       die; 
     } 
     // Access Granted 
?> 

的代碼的一個特殊代碼部分,但是,一個是沒有必要的,用戶名可以與/somecode.php?username=選擇」或‘1’=‘1 &密碼=東西,但’或者不能使用密碼,任何人都可以幫助我嗎?

問候

+1

您是否查詢SQL注入? – ceejayoz 2012-03-13 18:26:40

+0

(在xkcd.com/327/有一個很好的入門書籍) – rjz 2012-03-13 18:28:58

+3

你爲什麼使用陳舊的'mysql_ *'函數。使用PDO! – webbiedave 2012-03-13 18:30:17

回答

2

不要動態建立你的SQL代碼 - 通用戶輸入參數。

請參閱PHP文檔中的this example

如果動態建立這樣的SQL:

$res = mysql_query("SELECT id FROM users WHERE username = '$username'"); 

其中$username可能含有直接由用戶提供的東西,那麼你就處於危險之中。使用諸如預準備語句之類的解決方案,用戶不可能直接影響正在執行的實際SQL查詢,這是一種更安全的選擇。

1

問題是這一行:

// validate the specified username 
    $res = mysql_query("SELECT id FROM users WHERE username = '$username'"); 

因爲$的用戶名是直接從用戶的人可以傳遞的test' OR id='1用戶名這將產生以下SQL:

SELECT ID FROM用戶WHERE username ='test'OR id ='1';

攻擊者現在已成爲ID爲1的用戶。糟糕!

您需要跳過$_GET['username']變量與addslashes()或類似的東西。

1

有幾個問題與代碼:

  • 您正在使用過時的API。代替古老的mysql_功能,您應該使用PDO準備好的語句
  • 存在SQL注入等待發生

而不是你的代碼應該看起來是這樣的:

$connection = new PDO('mysql:dbname=dbase;host=127.0.0.1', 'user' , 'password'); 
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 

$stmt = $connection->prepare('SELECT id FROM users WHERE username = :user'); 
$stmt->bindParam(':user', $_POST['username'], PDO::PARAM_STR, 128); 

if ($stmt->execute()) 
{ 
    var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); 
} 

補充閱讀: