我正在考虑这种转义方法的实际解决方案。mysql_query不会一次进行两个查询,因此攻击者不能使用' OR 1;删除用户;Select * from//他将猜测查询的其余部分。(它变得令人困惑)
(我显然不喜欢pdo,当你需要在每个类的每个函数中定义一个连接时,它在oop中是不实用的,否则我每次都必须使用$this或全局$dbc)
没有。除了隐藏单独的DML、DDL或语句之外,查询还有多种"不安全"的方式。例如:
- 一个大的,性能很差的子查询可以用来使你的数据库爬行。
- where子句的分支可以调用任意的存储过程,而不管它有什么效果。
和每个特定的查询都必须进行审查,以防止在中间插入随机代码的可能性。例如,如果查询结果将以某种方式呈现给用户,那么指向具有身份验证信息的表的子查询可能会让用户推断出大量信息。(想象一系列测试where exists (select 1 from app_users where username = 'JoeAdmin' and password like 'a%')
,然后是password like 'ba%'
,一旦b
被识别,以此类推。即使黑客最初不知道您有一个名为app_users
的表,他们也可以通过对系统表使用这种方法来快速找出。
转义的实际解决方案是:
$blah = mysql_real_escape_string($blah, $connection);
$num = (int)$num;
$sql = "select * from `test` where foo = '$blah' and num_col = $num";
每当您将变量插入SQL字符串时,都需要对其进行转义。无一例外。您应该尽可能在其嵌入点附近进行转义,以便在校对代码时更容易验证这是否发生。
如果只有一个连接,可以定义自己的函数:
function qescape($var)
{
global $connection;
return mysql_real_escape_string($var, $connection);
}
我对你说的这句话有很大的看法:
mysql_query不会同时进行两个查询,所以攻击者不能使用
虽然技术上是正确的,但它们可以做各种其他讨厌的事情,而不需要运行多个查询。一个好的黑客可能能够查看、修改和插入几乎任何他们想要的数据库,甚至不能够运行多个查询。
不,您仍然需要转义每个非数字类型,而不仅仅是最后一个参数。
检查用户名/密码匹配是否应该登录用户的示例:// Check username / password
SELECT user_id FROM users WHERE username = 'nickb' AND password = 'password'
如果只有最后一个参数被转义(password),那么我可以传递这个:
-
username="nickb' --"
导致:
SELECT user_id FROM users WHERE username = 'nickb'
此处,用户无需密码即可登录。
我不明白你的意思。
你为什么要采用这种方法?
有一些常规的转义/绑定/白名单方法。
为什么没有一个适合你?为什么要设计一些不寻常且无法使用的东西?
我已经告诉过你很多次了-逃避并不是为了"防止注射"。
它只是SQL语法规则的一部分。只有作为副作用,它可以保护字符串不被注入。
所以,无论如何,你必须转义(如果你不想绑定)你的字符串。
因此,像"只转义查询中的最后一个参数"这样的奇怪发明根本没有用。
明白了吗?