如何防止php和mysql的sql注入
我有一个访问者可以输入数据的表单,我想通过 $_POST 变量将此数据存储在 mysql 数据库中。我需要什么来防止sql注入?
I have a form into which the visitor can enter data, and I want to store this data in a mysql database via the $_POST variable. What do I need to prevent sql injection?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用准备好的语句。
Use prepared statements.
我在 2010 年 5 月的 PHP TEK-X 会议上就这个主题做了一次演讲,并尝试介绍多种防御 SQL 注入的方法。没有一种方法在所有情况下都是最佳的,因此您应该学习多种方法并使用所有这些方法:
在将其插入之前验证用户输入或来自外部源的任何其他内容(甚至来自您自己的数据库中的数据) SQL 查询。例如,您可以使用 PHP 的 过滤器 扩展或正则表达式。
强制外部内容采用正确的格式。例如,
(int) $_POST["userid"]
将该内容类型转换为普通整数,因此可以安全使用。当在 SQL 表达式中包含动态内容来代替文字值时,请使用带参数的准备好的查询。请注意,PHP 中的普通
mysql
扩展不支持查询参数 - 使用 PDO 。我不使用mysqli
因为它的 API 不一致且难以使用。使用
IN()
谓词时,不能将一个参数用于一组值。连接多个参数占位符,数量与列表中的值相同。这并不难,只需要一两行代码:当使用动态表名、列名或 SQL 关键字时,不能使用查询参数。您必须插入动态内容。但您可以使用白名单技术将不受信任的内容映射到合法、安全的标识符和关键字。
请参阅我的演示文稿SQL 注入神话和谬误了解更多信息和例子。
您也可能喜欢我的书 SQL 反模式卷 1:避免数据库编程的陷阱。我的书中有一章是关于 SQL 注入的。
I gave a presentation at the PHP TEK-X conference in May 2010 about this topic, and I tried to cover multiple methods for defending against SQL Injection. There is no single method that is best in all cases, so you should learn multiple methods and use all of them:
Validate user input or any other content from external sources (even data from within your own database) before interpolating it into an SQL query. You can use PHP's filter extension or regular expressions, for instance.
Force external content to be in correct format. For example,
(int) $_POST["userid"]
typecasts that content to be a plain integer, so it's safe to use.When including dynamic content in place of literal values in SQL expressions, use prepared queries with parameters. Note that the plain
mysql
extension in PHP does not support query parameters -- use PDO. I don't usemysqli
because its API is inconsistent and hard to use.When using the
IN()
predicate, you can't use one parameter for a list of values. Concatenate multiple parameter placeholders, as many as you have values in your list. This is not hard, it only take a line or two of code:When using dynamic table names, column names, or SQL keywords, you can't use query parameters. You have to interpolate dynamic content. But you can use whitelisting techniques to map the untrusted content to legal, safe identifiers and keywords.
See my presentation SQL Injection Myths and Fallacies for more information and examples.
Also you might like my book SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming. My book has a chapter about SQL Injection.
阅读本文,下次进行一些搜索:
https://stackoverflow.com/questions/1973/what-is-the-best-way-to-avoid-sql-injection-attacks
Have a read at this, and next time do some searching:
https://stackoverflow.com/questions/1973/what-is-the-best-way-to-avoid-sql-injection-attacks
在向查询添加任何数据时,您必须遵循一些规则,无论数据来自何处 - 来自用户或表单或其他任何内容。规则始终保持不变。
要将查询发送到数据库,您有 2 个选项:
以常规方式构建查询,使其看起来与可以在 sql 控制台中运行的 SQL 查询完全相同。
为此,人们应该了解一整套规则,而不仅仅是“使用 mysql_real_escape_string”。
规则例如:
单独发送查询和数据。
这是最优选的方式,因为它可以缩短为“使用绑定”。所有字符串、数字和 LIMIT 参数都可以绑定 - 完全不用担心。
使用此方法,带有占位符的查询将按原样发送到数据库,并且绑定数据将在单独的数据包中发送,因此它不会干扰。
这就像代码和数据分离一样。您发送与数据分开的程序(查询本身)。
上面所说的一切仅涉及数据插入。
但有时我们必须使查询更加动态,添加运算符或标识符。
在这种情况下,每个动态参数都应该在我们的脚本中进行硬编码,并从该集中进行选择。
例如,要进行动态排序:
或动态搜索:
在本示例中,我们仅向查询添加用户输入的数据,而不是字段名称,这些数据都硬编码在脚本中。
对于绑定,算法非常相似
等等。
You have to follow some rules while adding any data to the query, no matter from where it come - from user or form or anything. The rules always remain the same.
To send a query to the database, you have 2 options:
Build a query usual way, to make it look exactly as SQL query you can run in sql console.
To do it, one should understand a whole set of rules, not just "use mysql_real_escape_string".
Rules such as:
To send query and data separately.
This is most preferred way as it can be shortened to just "use binding". All strings, numbers and LIMIT parameters can be bound - no worry at all.
Using this method, your query with placeholders being sent to database as is, and bound data being sent in separate packets, so, it cannot interfere.
It is just like code and data separation. You send your program (query itself) separated from the data.
Everything said above covers only data insertion.
But sometimes we have to make our query even more dynamic, adding operators or identifiers.
In this case every dynamic parameter should be hardcoded in our script and chosen from that set.
For example, to do dynamic ordering:
or dynamic search:
in this example we're adding to the query only data entered by user, not field names, which are all hardcoded in the script.
For the binding the algorithm is very similar
And so on.