2012-07-10 64 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