遵循哪种方法来防止 SQL 在 MySql 存储过程中注入
which method to follow to prevent SQL injection in MySql Stored Procedure
嗨,朋友们,我用谷歌搜索了这个,发现其他人使用不同的方法来防止 sql 注入。我在最终确定遵循特定方法之前写在下面的存储过程中,我希望得到你们的建议。我应该遵循哪种方法。
下面是我的存储过程的例子,我在里面写了不同的方法
CREATE DEFINER=`root`@`localhost` PROCEDURE `spTestSQLInjection`(pSelfId VARCHAR(100),bIntSelfId BIGINT(20))
BEGIN
SET @sSelfId = pSelfId;
-- Method:1
-- below code is for injection
SET @selectQuery = CONCAT('select * from userProfile where userId = ',@sSelfId);
PREPARE stmt FROM @selectQuery;
EXECUTE stmt ;
DEALLOCATE PREPARE stmt;
-- Method:2
-- injection doesent affect below code
select * from userProfile where userId = @sSelfId;
-- Method:3
select * from userProfile where userId = bIntSelfId;
-- Method:4
SET @sSelectQuery=
'select * from userProfile where userId = ? ';
PREPARE stmtQuery FROM @sSelectQuery;
EXECUTE stmtQuery USING @sSelfId;
DEALLOCATE PREPARE stmtQuery;
END
在 workbench 中执行以下存储过程:
1)调用 spTestSQLInjection('231', 231);
结果:当我传递正确的数据时,结果集会为所有然后 4 种方法提供单个用户数据。
2)调用 spTestSQLInjection('231 OR 1=1', 231);
结果:当我传递“231 OR 1=1”数据时,结果集会给出方法 1 的所有用户数据和方法 2、3、4 的单个记录。
so conclused that method1 is prone to sql injection 所以不要遵循这个方法,因为它的动态查询
& 建议不要在存储过程中编写动态查询。
方法 2、方法 3 有效并给出了单个用户记录,这意味着此查询不易 sql 注入。
大多数开发人员建议 method4 遵循此方法以防止 sql 在存储过程中注入。但是我的
实时项目在存储过程中包含 20 到 30 个查询(insert/update/delete),因此编写准备好的语句
for all 很费时间。
所以指导我遵循哪个方法,方法2,方法3或方法4
在此先感谢您,我们将不胜感激。
方法 2、3 和 4 是安全的 SQL 注入,但方法 3 是最简单的解决方案。
CREATE DEFINER=`root`@`localhost` PROCEDURE `spTestSQLInjection`(pSelfId VARCHAR(100), bIntSelfId BIGINT(20))
BEGIN
-- Method:3
select * from userProfile where userId = bIntSelfId;
END
不需要创建用户自定义变量,因为过程参数bIntSelfId
已经是一个变量。
在这种情况下不需要使用参数或准备好的语句,因为变量仅被视为标量值。它不需要修改任何 SQL 语法,也不用作标识符,因此可以简单地在查询中使用,如上所示。
这假设您的 table 没有自己的同名列 bIntSelfId
。如果是这样,该标识符的使用将是不明确的。建议将您的参数命名为与您将使用该变量查询的 table 的任何列明显不同。使用用户定义的变量或查询参数也可以避免歧义。
嗨,朋友们,我用谷歌搜索了这个,发现其他人使用不同的方法来防止 sql 注入。我在最终确定遵循特定方法之前写在下面的存储过程中,我希望得到你们的建议。我应该遵循哪种方法。
下面是我的存储过程的例子,我在里面写了不同的方法
CREATE DEFINER=`root`@`localhost` PROCEDURE `spTestSQLInjection`(pSelfId VARCHAR(100),bIntSelfId BIGINT(20))
BEGIN
SET @sSelfId = pSelfId;
-- Method:1
-- below code is for injection
SET @selectQuery = CONCAT('select * from userProfile where userId = ',@sSelfId);
PREPARE stmt FROM @selectQuery;
EXECUTE stmt ;
DEALLOCATE PREPARE stmt;
-- Method:2
-- injection doesent affect below code
select * from userProfile where userId = @sSelfId;
-- Method:3
select * from userProfile where userId = bIntSelfId;
-- Method:4
SET @sSelectQuery=
'select * from userProfile where userId = ? ';
PREPARE stmtQuery FROM @sSelectQuery;
EXECUTE stmtQuery USING @sSelfId;
DEALLOCATE PREPARE stmtQuery;
END
在 workbench 中执行以下存储过程:
1)调用 spTestSQLInjection('231', 231);
结果:当我传递正确的数据时,结果集会为所有然后 4 种方法提供单个用户数据。
2)调用 spTestSQLInjection('231 OR 1=1', 231);
结果:当我传递“231 OR 1=1”数据时,结果集会给出方法 1 的所有用户数据和方法 2、3、4 的单个记录。 so conclused that method1 is prone to sql injection 所以不要遵循这个方法,因为它的动态查询 & 建议不要在存储过程中编写动态查询。
方法 2、方法 3 有效并给出了单个用户记录,这意味着此查询不易 sql 注入。
大多数开发人员建议method4 遵循此方法以防止 sql 在存储过程中注入。但是我的 实时项目在存储过程中包含 20 到 30 个查询(insert/update/delete),因此编写准备好的语句 for all 很费时间。
所以指导我遵循哪个方法,方法2,方法3或方法4
在此先感谢您,我们将不胜感激。
方法 2、3 和 4 是安全的 SQL 注入,但方法 3 是最简单的解决方案。
CREATE DEFINER=`root`@`localhost` PROCEDURE `spTestSQLInjection`(pSelfId VARCHAR(100), bIntSelfId BIGINT(20))
BEGIN
-- Method:3
select * from userProfile where userId = bIntSelfId;
END
不需要创建用户自定义变量,因为过程参数bIntSelfId
已经是一个变量。
在这种情况下不需要使用参数或准备好的语句,因为变量仅被视为标量值。它不需要修改任何 SQL 语法,也不用作标识符,因此可以简单地在查询中使用,如上所示。
这假设您的 table 没有自己的同名列 bIntSelfId
。如果是这样,该标识符的使用将是不明确的。建议将您的参数命名为与您将使用该变量查询的 table 的任何列明显不同。使用用户定义的变量或查询参数也可以避免歧义。