Php SQL注入、实数转义字符串和带引号的查询
首先-我知道准备好的声明是“银弹”,我“应该使用它们”-但是对于这个项目,它是不可行的。相信我,我说这不会发生。所以,在布道开始之前……;) 所以,我今晚已经阅读了4个小时的SQL注入 对于使用real_escape_string(我正在使用PHP和MySQL)的每一次反驳都说,基本上,real_escape_string不会阻止这一点:Php SQL注入、实数转义字符串和带引号的查询,php,mysql,sql-injection,Php,Mysql,Sql Injection,首先-我知道准备好的声明是“银弹”,我“应该使用它们”-但是对于这个项目,它是不可行的。相信我,我说这不会发生。所以,在布道开始之前……;) 所以,我今晚已经阅读了4个小时的SQL注入 对于使用real_escape_string(我正在使用PHP和MySQL)的每一次反驳都说,基本上,real_escape_string不会阻止这一点: SELECT * FROM something WHERE id=1 or 1=1; 对。明白了 但自从15年前我第一次接触mysql以来,我编写的每个查询
SELECT * FROM something WHERE id=1 or 1=1;
对。明白了
但自从15年前我第一次接触mysql以来,我编写的每个查询都会引用我在查询中发送的所有参数。比如,如果我不使用单引号参数,我会有这样的感觉:查询将失败。所以我总是引用单引号。全部的这个时间
以及:
这怎么可能被打破呢?可以吗?我从来没有看到过一个例子,它击落了不使用无引号版本的real_escape_字符串
在引号里。所有可能脱离引用的内部引用都被转义
再说一遍:我知道事先准备好的陈述是最好的。这不是我要问的。我在问我上面写的东西是否能被破坏
我没有办法。我相信你的代码是安全的。由于您已将字符串用引号括起来,因此将
或
解释为SQL关键字的唯一方法是让输入包含一个结束引号。但是real\u escape\u string
将对此进行转义,因此它不会结束字符串
对于要求为整数的值,您还可以执行以下操作:
$clean = (int)$_POST['userinput'];
这将把输入的
1或1=1
转换为1
对整数使用intval()
。<>如果你计划放大,认真考虑重写你所有的查询;您甚至可以在使用最新技术和mysql增强功能的同时提高性能,因此这并不是完全的损失。事实上,prepared语句不是一项功能,而是一项原则。一个人可以自己实现它。你必须这样做,而不是设计借口 格式化字符串文字的想法是正确的。然而,这种格式化必须通过预先准备好的语句来完成 您正在使用的手动格式是分离的,可以分离。你在一个地方加引号,在另一个地方转义引号——这本身就是许多灾难的根源。即使您将其移动到一个地方,您的格式仍然是可分离的,这意味着它可以移动到远离实际查询执行的某个地方,并被遗忘在那里 这就是为什么您应该始终使用占位符来表示查询中的变量,然后在替换时格式化数据
这就是为什么我们准备了一个银弹,而不是因为刚才有人告诉过你。操作码是“安全的”。
real\u escape\u函数
识别输入字符串中的“危险”字符,并返回要包含在SQL语句中的“安全”字符串,如果这也是以“安全”的方式完成的,如OP示例中所示,则将其括在SQL文本中的单引号中。或者通过使用(int)
强制转换为int来避免函数调用,如果您有心情进行微优化,那么您就不会使用PHP;-)我总是把INT传递给INSERT,或者选择单引号,没有问题。它总是有效的。引用它是否存在性能问题?IE:为什么要将其转换为int并取消其引号?如果不使用magic_引号,也不转义输入,也不将其转换为整数,那么它很容易受到sql注入的影响。我已经阅读了准备好的语句,它们实际上会减慢查询速度,除非您反复运行同一个查询。这适用于一个数据库繁重的web应用程序,其中页面加载、执行许多不同的sql查询(不重复任何查询),然后退出。显然,一旦页面加载停止,就无法使准备好的语句保持“活动”。那么性能改进在哪里呢?哦,我之前读过这篇文章——这基本上只适用于使用旧版本的MySQL和/或使用一些非标准字符集的情况。我永远不会将我的字符集设置为GBK,我的MySQL是现代的,所以这不是问题。事实并非如此,一个不会从参数查询中看到性能提高的应用程序是极不可能的。以下是一些文章:这些文章是否相关/正确?那些文章已经有8年历史了。我读过的所有东西都说,如果只使用一次,准备好的语句会慢一些——它们是为重复使用而设计的。一次性陈述总是比只使用一次准备好的陈述要快。谢谢我说我不想听的演讲。
$clean = (int)$_POST['userinput'];