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

发布于 2024-12-08 16:11:01 字数 620 浏览 1 评论 0原文

哪个查询更安全?

我什至听说过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

Which query is more EXTRA secure?

I have even heard salt(); and md5(); in php5 would been extra secure for mySQL insertion.

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

Or even this, I thought of:

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

$xx = mysql_real_escape_string(($a));

My original thread: https://stackoverflow.com/questions/7633993/php-mysql-select-how-to-make-it-secure

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

顾铮苏瑾 2024-12-15 16:11:01

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

None of your queries are more secure than the other. One of them converts the string to all lowercase and trims whitespace. This doesn't do anything to prevent a SQL injection. Your last query is the same as a plain mysql_real_escape_string($_REQUEST['customers_email']);.

温馨耳语 2024-12-15 16:11:01

这个问题之前已经被问过很多次了。

最好使用 PDO,但如果必须使用 mysql_* 库,请按如下方式操作:

参数转义
以下代码是 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

另请参阅:
如何防止使用动态表名进行 SQL 注入?
“Bobby Tables”XKCD 漫画中的 SQL 注入是如何工作的?
如何防止 PHP 中的 SQL 注入?

This question has been asked many many times before.

It's always best to use PDO, but if you have to use the mysql_* lib, do it like this:

Escaping for parameters
The following code is 100% secure:

$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.

No further action is needed to make the code SQL-injection same.

Escaping for dynamic column/table names
This code:

Unsafe, does not work

$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.

This will not work, you need to check database, table and column names against a whitelist.

100% Safe for dynamic SQL

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

About hashing and salting
You only use salted hashes for passwords.
It is a bad idea to store unencrypted passwords in a database, instead you store a hashed password.
In order to defeat rainbow tables you have to salt the hash with a different semi-random salt; the salt does not need to be secret, it just needs to be somewhat random.

//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

See also:
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?

乞讨 2024-12-15 16:11:01

您的第一种方法彼此一样安全,因为它们使用 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 和准备好的语句,正如其他人在这里提到的那样。

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

Each of your first approaches are as secure as each other because they're using the mysql_real_escape_string function. SQL injection works by 'breaking out' of your query by introducing additional quote marks into your string that then break your conditions.

Consider:

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

If an attacker were to submit an email of ' OR 1=1 -- your query after string interpolation would become:

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

In this case, the double dash in MySQL is a comment, commenting our your original right quote mark. By running mysql_real_escape_string, the database engine will properly escape the email string to prevent the quote mark in it 'breaking out' of your query.

The exact escaping style of each database engine is different, so each engine has their own set of escape functions. For this reason, it would be wise to switch to using PDO and prepared statements as mentioned by the others here.

I hope this has explained this a little further.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文