所以你有
$sql = "SELECT * FROM `table` WHERE `some_text_field` LIKE CONCAT('%', ?, '%')";
$stmt = $dbh->prepare($sql);
$stmt->execute(array($_POST['badies_code']));
看看另一个问题,我发现这会引起安全问题,但为什么呢?
我找到了这个问题,一个被否决的答案和一个赞成的评论,这就是我问的原因
评论说
这不是执行此操作的正确方法。您不应该将 CONCAT() 用于三个静态字符串文字,因为它为您打开了特定类型的 SQL 注入(我忘记了名称)。——西奥多·
PHP PDO 准备语句 -- mysql LIKE 查询
记住不存在的注入名称将是一项相当复杂的任务。
将concat()
与预准备语句一起使用并没有错。
我认为@TheodoreR.Smith的意思可能是Oracle数据库中所谓的横向SQL注入[1][2]。
它的工作原理是更改保存格式信息(如 NLS_DATE_FORMAT
或 NLS_NUMERIC_CHARACTERS
)的环境变量,这些信息随后用于动态构建和执行语句的存储过程(这是使用字符串连接的地方,由||
运算符表示):
CREATE OR REPLACE PROCEDURE date_proc IS
stmt VARCHAR2(200);
v_date DATE := SYSDATE;
BEGIN
stmt := 'select object_name from all_objects where created = ''' || v_date || '''';
EXECUTE IMMEDIATE stmt;
END;
在这里SYSDATE
以 NLS_DATE_FORMAT
中指定的格式返回当前日期。尽管该过程没有参数,但将日期格式更改为类似 ' or 1=1--
:
ALTER SESSION SET NLS_DATE_FORMAT = ''' or 1=1--'
生成的语句为:
select object_name from all_objects where created = '' or 1=1--'
此环境变量操作特定于 Oracle 数据库。同样,可以使用预准备语句来缓解它:
CREATE OR REPLACE PROCEDURE date_proc IS
stmt VARCHAR2(200);
v_date DATE := SYSDATE;
BEGIN
stmt := 'select object_name from all_objects where created = :date';
EXEC SQL PREPARE prepared_stmt FROM :stmt;
EXEC SQL EXECUTE prepared_stmt USING :v_date;
end;
我不知道MySQL容易进行这种环境变量操作。
但是,在没有正确处理的情况下动态构建语句很容易出现 SQL 注入,无论它发生在应用程序中还是在数据库中。因此,在存储过程中使用预准备语句也是强制性的。