Mysql 显示此存储过程的注入攻击

Mysql 显示此存储过程的注入攻击,mysql,sql-injection,Mysql,Sql Injection,我注意到很多人都说可以创建注入攻击,但我的理解是,如果有人使用字符串而不是参数创建查询。为了测试存储过程不能保护您免受注入攻击的说法,我举了这个例子,希望有人能向我展示一个漏洞(如果有) 请注意,我以这种方式构建代码,以便轻松插入调用过程的函数并将其嵌入SELECT查询。这意味着我不能创建一个准备好的语句。理想情况下,我希望保持这样的设置,因为它是动态和快速的,但如果有人能够创建一个有效的注入攻击,显然这是不会发生的 DELIMITER $$ #This procedure searches

我注意到很多人都说可以创建注入攻击,但我的理解是,如果有人使用字符串而不是参数创建查询。为了测试存储过程不能保护您免受注入攻击的说法,我举了这个例子,希望有人能向我展示一个漏洞(如果有)

请注意,我以这种方式构建代码,以便轻松插入调用过程的函数并将其嵌入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等进行更新。如果发现新漏洞,我仍然欢迎任何其他评论。)

最终结果是

table `table`
id      name
1       oak
2       mahogany
如果我想让橡树变成桃花心木的孩子,我可以用

add_relationship("mahogany","oak");
add_relationship("oak","plastic");
如果我想做橡树的孩子,我可以用

add_relationship("mahogany","oak");
add_relationship("oak","plastic");

希望这有助于提供一些框架和上下文。

存储过程不一定是不安全的,而是您调用它的方式

例如,如果您执行以下操作:

mysqli_multi_query("CALL id_insert_or_find(" + $value + ", " + $id + ")");
然后,攻击者将设置
$value=“'attack]”和id=“1”;删除您的\u DB;-”

那么结果就是

mysqli_multi_query("CALL id_insert_or_find('attack', 1); DROP SCHEMA YOUR_DB; --)");

BOOM DEAD

严格来说,应该编写该查询以转义表名:

$db->query("INSERT INTO table_relationships (`table_id`,`tableChild_id`) " .
    "VALUES (get_id(" . $db->quote($table_name) + ")," .
    "get_id(" . $db->quote($table_name_child) . "))");
否则,如果其中一个参数包含一个引号,它将断开引号。如果您只在代码中使用文字字符串调用该函数(例如,
add_relationship(“mahogany”、“oak”);
),那么不转义它是安全的。如果您可能使用来自$\u GET/$\u POST/$\u COOKIE或其他数据库字段或文件等的数据调用
add\u relationship
,这是自找麻烦。我当然不会让它通过代码审查

如果用户可以控制提供给该函数的表名,则可以执行以下操作,例如:

add_relationship("oak", "'+(SELECT CONCAT_WS(',', password_hash, password_salt) FROM users WHERE username='admin')+'");
现在您可能会说,如果生成的表名不存在,则没有实际的方法提取该信息,但即使如此,您仍然可以使用二进制搜索和单独的查询一次提取一个二进制位的信息,只需中断查询即可。类似于以下内容(未测试确切语法):


实际上,只需转义参数就更容易了,这样您就不必担心了。

这段代码中不可能存在注入攻击,因为只有在从字符串构建查询时才可能发生注入攻击。要么说易受攻击的人是白痴,要么他们指的是调用此过程的PHP/Java/etc代码。谢谢Boann。这就是我要找的。我将等待其他答案,但这是我的怀疑。我曾试图以这种方式注入代码(用插入查询代替删除模式),但没有成功。除此之外,这种草率的编码将由我承担。我甚至没有用代码调用这个过程。恕我直言,我认为你在这里是错的。@Jones好吧,数据库不仅仅是自己站起来做事情,所以你一定是从某个地方,不知何故,给它打了电话。在显示调用代码之前,您不会得到关于是否存在漏洞的真实答案。如果您只向我们展示SQL代码,那么“是否存在注入漏洞?”问题的答案将始终是否定的,不管它是做什么的。当然,有权限级别和防止多个查询来帮助阻止此类攻击尝试登录。它让我通过振铃器查看我的代码是否有这种漏洞,但事实并非如此。如果你一开始就看到我的代码,那会有帮助的。你说得很对,博恩。我通常会执行db->prepare、stmt->bind_param,但在本例中排除了它。那是我的疏忽。