2012-07-10 63 views
2

我在本地主機上有一個簡單的註冊表單(仍在測試),我想知道它是否可以被SQL注入攻擊?在註冊表格中避免SQL注入php

代碼:

$name = mysql_real_escape_string($_POST['name']); 
$password = mysql_real_escape_string($_POST['password']); 
$password = md5($password); 
$email = mysql_real_escape_string($_POST['email']); 
$refId = $_GET['refid']; 
$ip = $_SERVER['REMOTE_ADDR']; 


$add = mysql_query("INSERT INTO `users` (`name`, `password`, `email`, `refId`, `ip`) 
VALUES('$name','$password','$email','$refId', '$ip')") or die(mysql_error()); 

那是安全的,也可以使用別人SQL注入(我想知道怎麼樣)?我怎樣才能避免注射?

+0

您是否已閱讀此文件(http://stackoverflow.com/questions/60174/best-way-to-prevent-sql-injection-in-php)?準備好的語句,並儘可能安全:使用主DB和存儲過程,如果需要的話,用你自己的函數解析字符串 – 2012-07-10 17:00:55

+2

避免使用mysql_庫注入需要你爲每一個單獨的事情做這樣的單調乏味的事情查詢,即使如此,你也不能保證安全。避免注入的標準方法是使用預先準備好的查詢,它告訴數據庫引擎,它不必將您傳遞的字符串視爲您指定的查詢中的參數以外的任何內容。 PHP有兩個庫,mysqli和PDO。谷歌他們並閱讀準備好的查詢。它需要更多的工作來設置,但它是值得的。 – octern 2012-07-10 17:00:58

+0

存儲過程不是必需的,以避免SQL注入,雖然這將工作;準備好的語句是最簡單的方法,或者像Doctrine或Propel這樣的ORM。 – halfer 2012-07-10 17:03:23

回答

5

確實很脆弱;你還沒有逃脫$_GET['refid']。以此URL爲例:

yourpage.php?refid='%2C'')%3B%20DROP%20TABLE%20users%3B-- 

避免SQL注入很容易。使用準備好的語句和PDO。例如:

$query = $dbh->prepare("INSERT INTO `users`(`name`, `password`, `email`, `refId`, `ip`) 
VALUES(:name, :password, :email, :refId, :ip)"); 
$query->bindValue(':name', $_POST['name']); 
$query->bindValue(':password', md5($_POST['password'])); # Do not use MD5 for password hashing, and especially not without salt. 
$query->bindValue(':email', $_POST['email']); 
$query->bindValue(':refid', $_GET['refid']); 
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']); 
$query->execute(); 
+0

從未使用Md5,即使用鹽。至少使用sha2之類的東西,最多使用PBKDF2 – CountMurphy 2012-07-10 17:12:42

+1

@CountMurphy:就個人而言,我會推薦bcrypt--而且不僅是最多的,也是最多的。 – 2012-07-10 17:13:23

+0

忘記了bcrypt。好決定。 – CountMurphy 2012-07-10 17:15:01

4

你沒有mysql_real_escape_string$refId,儘管這是一個從$_GET抓起。這基本上使所有其他注射預防措施都沒有意義。在切線上,如果在md5-ing之前轉義密碼串,它會更改散列值。

6

避免注射的最佳方法是使用Prepared Statements
對於準備好的語句,我更喜歡使用PDO來處理我所有的數據庫內容。這裏是一些PDO示例代碼我寫的檢索一些基本的登錄信息:

$sql=new PDO("mysql:host=127.0.0.1;dbname=name","user","password"); 
     $user=$_POST[user]; 

     $query="select Salt,Passwd from User 
       where Name=:user"; 
     $stmt=$sql->prepare($query); 
     $stmt->bindParam(':user',$user); 
     $stmt->execute(); 
     $dr=$stmt->fetch();   
     $sql=null; 
     $password=$_POST[pass]; 
     $salt=$dr['Salt']; 

...等

閱讀this對PDO頁面瞭解更多信息。如果你想知道每行代碼在做什麼,請閱讀this我給另一篇文章的答案。

+0

你有不同的鹽每個用戶?我喜歡。 – jcho360 2012-07-10 17:12:39

+0

好吧,如果他們都有相同的鹽,它有點擊敗目的;) – CountMurphy 2012-07-10 17:17:19