我注意到很多人都说可以创建注入攻击,但我的理解是,如果有人从字符串而不是参数创建查询。为了测试存储过程不能保护您免受注入攻击的说法,我提出这个例子是希望有人可以向我展示一个漏洞(如果有的话)。
请注意,我以这种方式构建了代码,以便轻松插入调用过程的函数并将其嵌入到 SELECT 查询中。这意味着我无法创建准备好的语句。理想情况下,我希望以这种方式保持我的设置,因为它是动态且快速的,但如果有人可以创建有效的注入攻击,显然这不会发生。
DELIMITER $$
#This procedure searches for an object by a unique name in the table.
#If it is not found, it inserts. Either way, the ID of the object
#is returned.
CREATE PROCEDURE `id_insert_or_find` (in _value char(200), out _id bigint(20))
BEGIN
SET @_value = _value;
SET @id = NULL;
SELECT id INTO _id FROM `table` WHERE name=_value;
IF _id IS NULL THEN
BEGIN
INSERT INTO `table` (`name`) VALUE (_value);
SELECT LAST_INSERT_ID() INTO _id;
END;
END IF;
END$$
CREATE FUNCTION `get_id` (_object_name char(200)) RETURNS INT DETERMINISTIC
BEGIN
SET @id = NULL;
call `id_insert_or_find`(_object_name,@id);
return @id;
END$$
PHP 代码
我在这里使用的 PHP 代码是:
(注意,Boann 在下面指出了这段代码的愚蠢之处。我不是为了尊重答案而对其进行编辑,但它肯定不会是代码中的直接查询。它将使用 ->prepare 进行更新,等等。如果发现新的漏洞,我仍然欢迎任何额外的评论。)
function add_relationship($table_name,$table_name_child) {
#This table updates a separate table which has
#parent/child relationships listed.
$db->query("INSERT INTO table_relationships (`table_id`,`tableChild_id`) VALUES (get_id('{$table_name}'),get_id('{$table_name_child}')");
}
最终结果是
table `table`
id name
1 oak
2 mahogany
现在,如果我想让橡木成为桃花心木的孩子,我可以使用
add_relationship("mahogany","oak");
如果我想让塑料成为橡木的孩子,我可以使用
add_relationship("oak","plastic");
希望这有助于提供一些框架和背景。