Mysql 更改分隔符以获得更好的 SQL INJECTION 处理?
我正在使用 mysql 并试图阻止那些尝试使用我的单个查询运行多个查询的人的不需要的查询注入。即,例如当我有参数“?id = 3”时,人们可以尝试使用“id = 3;drop table users”来运行它
现在,我知道避免这种情况的最佳方法是解析和检查参数,但有没有办法更改连接查询分隔符“;”类似于“%^#$%@#$^$”?
I am using mysql and trying to block unwanted queries injection of people who will try to use my single query to run several ones. ie, for example when i have the parameter "?id=3", people can try to run it with ="id=3;drop table users"
Now, i know that the best way to avoid this is by parsing and checking the parameter, but is there a way to change the concatenated queries delimiter from ";" to something like "%^#$%@#$^$"?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
通过默默无闻来保证安全是没有用的。花时间编写正确的代码来防止 SQL 注入攻击。预先执行此操作比成功攻击代码后执行此操作花费的成本要少得多!
Security through obscurity is useless. Take the time to write the proper code to protect against the SQL injection attacks. Doing it up front will cost you a lot less than doing it after you've had a successful attack run against your code!
语句
DELIMITER
配置是仅在mysql客户端工具中的内置命令。您无法更改多语句<的分隔符/a>.它始终是分号。此外,默认情况下,MySQL API 一次只允许执行一个语句。除非您明确 启用多语句。
此外,多语句并不是 SQL 注入的唯一向量。即使您可以更改语句分隔符,它也不会采取任何措施来防止修改单个给定语句的 SQL 注入。
在此示例中,如果
$id
的值为“1234 OR 1=1
”,则攻击者已更改所有帐户的密码,其中可能包括特权用户。但没有涉及多语句。编写代码时仍然需要注意安全问题。没有什么灵丹妙药可以防止 SQL 注入。
即使查询参数也不是 SQL 注入的万灵药。参数仅代替 SQL 表达式中的值。在许多常见情况下,仍然需要将应用程序变量插入 SQL 字符串。例如,当参数化
IN()
谓词时,或选择ORDER BY
表达式时。不要听那些说准备好的查询可以 100% 防止安全缺陷的人的话。另请参阅我的演示文稿 SQL 注入神话和谬误,或者我的书中有关 SQL 注入的章节 SQL 反模式卷 1:避免数据库编程的陷阱。
The statement
DELIMITER
configuration is a built-in command only in the mysql client tool. You can't change the delimiter for multi-statements. It's always semicolon.Also, the MySQL API allows execution of only one statement at a time, by default. The example you're talking about doesn't work unless you explicitly enable multi-statements.
Furthermore, multi-statements isn't the only vector for SQL injection. Even if you could change the statement delimiter, it wouldn't do anything to protect against SQL injection that modifies a single given statement.
In this example, if
$id
has a value of "1234 OR 1=1
" then the attacker has changed the password for all accounts, including probably a privileged user. And yet no multi-statements were involved.You still need to be mindful of security issues when you write code. There's no silver bullet to protect against SQL injection.
Even query parameters aren't a cure-all for SQL injection. Parameters take the place only of values in SQL expressions. There are many common cases where it's still necessary to interpolate application variables into an SQL string. For example, when parameterizing an
IN()
predicate, or when choosingORDER BY
expressions. Don't listen to people who say prepared queries are 100% proof against security flaws.See also my presentation SQL Injection Myths and Fallacies, or the chapter on SQL Injection in my book, SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.
防御注入攻击的最佳方法是使用 Prepared statements< /a>.
通过使用准备好的语句,您可以免受大多数注入攻击(当然,这不是您需要考虑的唯一安全漏洞,但它们是一个非常重要的漏洞。)
The best way to defend against injection attacks is to use Prepared Statements.
By using Prepared Statements, you are immune to most injection attacks (which of course aren't the only security vulnerability you need to think about, but they're a pretty major one.)
当您调用 mysql_query 或 mysql_real_query 时,它无论如何都不会运行多个语句,因此语句分隔符并不重要。您可以连接时为每个查询启用多个语句,但由于您试图避免这种能力,所以就不要启用它。
避免 SQL 注入的更好选择是 使用准备好的语句。从
mysql_stmt_init
和 < code>mysql_stmt_prepare 中包含语句参数的占位符,然后在mysql_stmt_execute
之前使用mysql_stmt_bind_param
填充参数。如果您不直接调用 API,那么您拥有的任何包装器库也应该提供对准备好的语句的支持。 (如果不支持它们,请考虑切换到更好的包装器。)When you call
mysql_query
ormysql_real_query
, it won't run multiple statements anyway, so the statement delimiter doesn't really matter. You can enable multiple statements per query when you connect, but since you're trying to avoid that ability, simply don't enable it.An even better option for avoid SQL injection is to use prepared statements. Start with
mysql_stmt_init
andmysql_stmt_prepare
with placeholders for your statement's parameters, and then fill in the parameters withmysql_stmt_bind_param
beforemysql_stmt_execute
. If you're not calling the API directly, then whatever wrapper library you have should also provide support for prepared statements. (If it doesn't support them, then consider switching to a better wrapper.)