仅使用 php 防止 SQL 注入
我的想法是,我有一个完整的工作网站,其中有许多对 MySQL 服务器的调用,并在这个网站上做了一些研究,我看到以这种形式进行查询:
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
我可以解决安全问题,但是,正如我所说,我有很多调用 MySQL 服务器,解决问题的最佳方法(就我而言)是直接访问传递给查询的变量,但不使用 MySQL 函数,因为我不在查询中。让我解释一下,我有这个:
mysql_query("SELECT * FROM `post` WHERE id=" . $_GET['edit']);
我无法对此查询进行修改,因为我的所有代码中有很多这样的内容,我更喜欢检查 var $_GET['edit'] 上的注入。
我如何使用纯 PHP 检查查询变量上的 SQL 注入?喜欢:
$_GET['edit']=freehack($_GET['edit']);
The think is that i have a complete working website with many calls to the MySQL server and doing some research on this site i saw that making my querys in this form:
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
I can solve the security issue, but, as i said, i have many calls to the MySQL server, and the best way (in my case) to solve the problem is going directly to the vars im passing to the query but whitout using a MySQL function because im out of the query. Let me explain it, i have this:
mysql_query("SELECT * FROM `post` WHERE id=" . $_GET['edit']);
I cant do modifications to this query because i have a lot of this in all my code, insted i preefer to check for injections on the var, $_GET['edit'].
How can i using pure PHP check for SQL injections on the variables of the querys? Like:
$_GET['edit']=freehack($_GET['edit']);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不要这样做。通过将
$_GET
参数的值替换为“安全”版本,您会污染您的输入数据,而其他地方可能需要这些数据。仅当需要在数据库层使用数据时才转义数据。它只需要你一点时间来解决你的问题,从长远来看,会给你省去很多麻烦。
无论如何,你所做的仍然不安全!请参阅:PHP:mysql_real_escape_string足以清理用户输入吗?
你真的应该使用使用 PDO 准备查询。此外,您应该在查询中使用用户输入之前检查其有效性。
Don't do it this way. By replacing the value of your
$_GET
parameters with "safe" versions, you are contaminating your input data, which you may need for other places.Only escape data when you need to use it on the database layer. It will only take you a little time to fix your queries, and will save you a ton of headache in the long run.
In any case, what you are doing is still not secure! See: PHP: Is mysql_real_escape_string sufficient for cleaning user input?
You really should be using prepared queries with PDO. Also, you should be checking your user input for validity before using it in a query.
在谈论安全性时,“我无法对此查询进行修改,因为我的所有代码中有很多这样的内容”是错误的态度。你所面临的一个重大设计问题会让你面临各种安全问题。即使您执行了类似于最后描述的过滤方法的操作,您也不能确定您会涵盖所有情况。
您确实应该使用某种数据库访问类来查询数据库,而不是在整个代码中进行这样的随机调用。这样,您只需编写一次清理代码,就可以绝对确保它在任何地方都被调用。为了获得更高的安全性,重构是值得的。
"I cant do modifications to this query because i have a lot of this in all my code" is the wrong attitude when talking about security. What you have there is a major design problem that opens you up to all sorts of security issues. Even if you do something like the filter method you describe at the end there, you can't be sure you'll cover every case.
You should really be using some sort of database access class to query the DB instead of making random calls like this throughout your code. This way you can write the sanitization code once and can be absolutely sure it is called everywhere. Refactoring is worth it for the added security you'll get.
我认为您可以将查询包装在 PDO。
where
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
然后你必须编写某种脚本来进行替换。然后再次,我真的认为你应该从头开始重写你的代码,因为它真的很难看。正确的单元测试、PDO、CSRF 保护、OOP 等。
I think you could wrap your query inside PDO.
where
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
Then you have to write some sort of scripts to do the replacements.Then again I really think you should be rewriting your code from scratch because it is really ugly. Properly unit tested, PDO, CSRF-protection, OOP etc.
我建议使用 PDO 界面,或 MySQLi 接口,因为两者都支持使用准备好的查询。使用准备好的查询是有效且一致地保护自己免受 SQL 注入攻击的唯一方法。我个人推荐 PDO 而不是 mysqli,因为它为您的数据库提供了一个与数据库无关的接口,以防您需要切换数据库。即使您永远不需要切换数据库,最好只学习 1 个接口,以防您需要使用不同的数据库来处理另一个项目。
I would recommend using the PDO interface, or the MySQLi inteface as both support using prepared queries. Using prepared queries is the only way to effectively and consistently protect yourself again SQL Injection attacks. I personally recommend PDO over mysqli as it provides a database agnostic interface to your database, in case you ever need to switch databases. Even if you never need to switch databases, it's better to only have to learn 1 interface, in case you need to work an another project using a different database.
我不会使用“神奇”函数并期望它能够清理变量。这并不能解决所有的边缘情况,而且仍然容易受到攻击。
你的第二个查询就是一个很好的例子。即使您
mysql_real_escape_string
$_GET['edit']
变量,它仍然容易受到 SQL 注入攻击。您需要做的是验证您收到的所有数据并检查它是否是您期望的数据类型。
清理只是确保数据正确显示并且不会造成问题。您不应该依赖清理来验证数据。
如果您想正确完成验证和清理,可以使用 ESAPI for PHP< /a>.
I wouldn't go with a "magic" function and expect it to clean the variables. This won't solve all the edge case and it will still be vulnerable.
A good example of this is your 2nd query. It's still vulnerable to SQL injection even if you
mysql_real_escape_string
the$_GET['edit']
variable.What you need to do is validate all the data you receive and check if it's the kind of data you expect.
Sanitizing is only there make sure the data will be properly display and won't cause problem. You shouldn't rely on sanitizing for the validation of your data.
If you want to get the validation and the sanitizing done right you can use the ESAPI for PHP.
避免在应用程序的不同位置重复相同的查询 - 随着事情的发展,您需要维护多个版本,并且它们几乎总是会不同步。准备好的查询对我来说听起来不错(我不是一个真正的 PHP 专家),或者如果您必须采取另一种方式设置一个中央参考库并将您的查询存储在其中,然后在您的应用程序中需要它们时引用它们。< /p>
不要存储编码数据,很容易忘记哪些变量被编码,哪些变量没有编码,而且一旦您必须将数据用于不同编码的目的,您就会遇到麻烦。在此过程中尽可能晚地进行编码,最好是在将其放入需要编码的最终情况时进行编码,以便快速检查可以显示编码已完成。
如果你必须...... SQL注入是一个明显的类型安全问题。如果您知道需要整数参数,则“1; drop table users;--”不是有效输入,即使其中没有任何危险字符或转义序列。不要只检查字符串或其他内容的破坏,确保当您需要特定类型时,您会得到该类型,并且其他输入会引发错误。
Avoid having the same query repeated in different places across your application - as things grow you have multiple versions to maintain and they almost invariably get out of sync. Prepared queries sounds good to me (I'm not really a PHP guy), or if you have to go another way set up a central reference library and store your queries in there, then reference them when you need them in your app.
Don't store encoded data, it's too easy to forget which variables are encoded and which aren't, plus you end up in trouble as soon as you have to use your data for a purpose with a different encoding. Encode as late as possible in the process, ideally when it's being put into the final situation where it needs encoding so that a quick inspection can show it's being done.
If you have to.... SQL Injection is significantly a type safety issue. If you know you're expecting an integer parameter, "1; drop table users;--" isn't valid input even though it doesn't have any danger characters or escape sequences in it. Don't just check for busting out of strings or whatever, make sure that when you want a specific type, you get that and other input throws an error.