哪个MySQL查询更安全?第2部分

时间:2011-10-07 11:20:20

标签: php mysql sql-injection

哪个查询更安全?

我甚至听说过 salt();和php5中的md5(); 对于mySQL插入来说是非常安全的。

$customers_email = mysql_real_escape_string(trim(strtolower($_REQUEST['customers_email'])));    
$customers_email = mysql_real_escape_string(($_REQUEST['customers_email']));

或者甚至是这个,我想到了:

$1=$_REQUEST['customers_email'];
$2=$1;
$3=$2;
$4=$3;
$5=$4;
$a=$5;

$xx = mysql_real_escape_string(($a));

我的原帖:https://stackoverflow.com/questions/7633993/php-mysql-select-how-to-make-it-secure

3 个答案:

答案 0 :(得分:3)

之前已经多次询问过这个问题。

最好使用PDO,但是如果你必须使用mysql_ * lib,那就这样做:

转义参数
以下代码是100%安全的:

$var = mysql_real_escape_string($_POST['var']);  
$query = "SELECT * FROM table1 WHERE afield = '$var' "
// You must quote your $vars                  ^    ^
// failure to do so defeats the escaping and causes syntax errors.

不需要进一步的操作来使代码SQL注入相同。

转义动态列/表名称
这段代码:

不安全,无法使用

$afield = mysql_real_escape_string('$_POST['var']);  
$query = "SELECT * FROM table1 WHERE `$afield` = 1 "
//You can only use escaping for values, never for dynamic SQL.

这不起作用,您需要针对白名单检查数据库,表和列名称。

动态SQL 100%安全

$allowed_fields = array('field1', 'field2');
$afield = $_POST['afield'];
if (in_array($afield, $allowed_fields)) {
    $query = "SELECT * FROM table1 WHERE `$afield` = 1";
}

关于哈希和腌制
您只使用盐渍哈希作为密码 将未加密的密码存储在数据库中是一个坏主意,而不是存储散列密码 为了打败彩虹表,你必须用不同的半随机盐来加盐。盐不需要保密,只需要有点随机。

//To add a user.
INSERT INTO users (name, salt, passhash) 
VALUES ('$username', '$salt', SHA2(CONCAT('$salt','$password'),512));

//To check a password:
SELECT u.id FROM users u 
WHERE u.name = '$username' 
  AND passhash = SHA2(CONCAT(salt, '$password'),512);

//To change a password:
UPDATE users u SET passhash = SHA2(CONCAT(s.salt, '$newpassword'),512)
WHERE u.id = (SELECT u2.id FROM (
  SELECT u1.id FROM users u1 
  WHERE u1.name = '$username' 
  AND passhash = SHA2(CONCAT(u1.salt, '$oldpassword'),512) u2) s

另见:
How to prevent SQL injection with dynamic tablenames?
How does the SQL injection from the "Bobby Tables" XKCD comic work?
How can I prevent SQL injection in PHP?

答案 1 :(得分:3)

您的查询都不比其他查询更安全。其中一个将字符串转换为全部小写并修剪空格。这对阻止SQL注入没有任何作用。您的上一个查询与普通mysql_real_escape_string($_REQUEST['customers_email']);相同。

答案 2 :(得分:2)

您的每个第一种方法都是相互安全的,因为它们使用的是mysql_real_escape_string函数。 SQL注入通过在您的字符串中引入额外的引号来突破您的条件来“突破”您的查询。

考虑:

$email = $_GET['email'];
$sql = "SELECT * FROM users WHERE email='$email'";

如果攻击者在字符串插值后将提交' OR 1=1 --您的查询的电子邮件:

$sql = "SELECT * FROM users WHERE email='' OR 1=1 -- '";

在这种情况下,MySQL中的双短划线是评论,评论我们原来的正确引号。通过运行mysql_real_escape_string,数据库引擎将正确地转义电子邮件字符串,以防止其中的引号标记“突破”您的查询。

每个数据库引擎的确切转义样式是不同的,因此每个引擎都有自己的转义函数集。出于这个原因,明智的做法是转而使用其他人在此处提到的PDO和预备语句。

我希望这进一步解释了这一点。