Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 如何在动态创建表时避免SQL注入风险?_Mysql_Sql Injection - Fatal编程技术网

Mysql 如何在动态创建表时避免SQL注入风险?

Mysql 如何在动态创建表时避免SQL注入风险?,mysql,sql-injection,Mysql,Sql Injection,以下是从用户提供的输入创建表的简单过程: PROCEDURE `hackProcedure`( IN tab_name VARCHAR(63)) BEGIN IF (tab_name REGEXP '^[A-Za-z0-9 ]+$') THEN SET @StB = CONCAT('CREATE TABLE tab_name (id INT(10) PRIMARY KEY NOT NULL UNIQUE AUTO_INCREMENT,

以下是从用户提供的输入创建表的简单过程:

PROCEDURE `hackProcedure`(
IN tab_name VARCHAR(63))
BEGIN

IF (tab_name REGEXP '^[A-Za-z0-9 ]+$')
THEN
    SET @StB = CONCAT('CREATE TABLE tab_name
                      (id INT(10) PRIMARY KEY NOT NULL UNIQUE AUTO_INCREMENT,
                      name VARCHAR(45),
                      guid VARCHAR(36));');
    PREPARE statementB FROM @StB;
    EXECUTE statementB;
    DEALLOCATE PREPARE statementB;
ELSE
    -- SIGNAL some error;
END IF;
#END

在创建表之前,我检查用户输入是否只包含alfa数值,因此据我所知,坏人尝试对该过程执行SQL注入不会成功,因为无法注释掉查询的其余部分,也无法添加其他列。这是安全的还是我遗漏了一些东西?

它不易受攻击,因为您向我们展示的代码使用了一个文本值作为表名,而不是参数。我想你想这样做:

CONCAT('CREATE TABLE ',  tab_name, '
                  (id INT(10) PRIMARY KEY NOT NULL UNIQUE AUTO_INCREMENT,
                  name VARCHAR(45),
                  guid VARCHAR(36));');
现在,如果我用…调用你的函数呢

dummy (id INT NOT NULL); DROP TABLE mysql.users; CREATE TABLE dummy2
?

它将失败,因为分号和括号将被正则表达式拒绝,但这远不是一个健壮的解决方案

在表名周围添加反勾引号(只要正则表达式不允许)是一个轻微的改进

 CONCAT('CREATE TABLE `',  tab_name, '`

它不易受攻击,因为您向我们展示的代码使用了表名的文本值,而不是参数。我想你想这样做:

CONCAT('CREATE TABLE ',  tab_name, '
                  (id INT(10) PRIMARY KEY NOT NULL UNIQUE AUTO_INCREMENT,
                  name VARCHAR(45),
                  guid VARCHAR(36));');
现在,如果我用…调用你的函数呢

dummy (id INT NOT NULL); DROP TABLE mysql.users; CREATE TABLE dummy2
?

它将失败,因为分号和括号将被正则表达式拒绝,但这远不是一个健壮的解决方案

在表名周围添加反勾引号(只要正则表达式不允许)是一个轻微的改进

 CONCAT('CREATE TABLE `',  tab_name, '`

首先允许用户(非DBA、非开发人员、通常不受信任的用户)创建表有点奇怪。这里的用例是什么?同意,为什么用户会对架构有任何控制权?@但在准备好的语句中不能将窗口表名替换为值。@deceze-如果您查看OP提出的上一个问题,Raymond发表了一条评论,说明如何使用准备好的语句创建名称来自用户输入的表。不过,解决方案并非万无一失。但是,您是对的,在语句中直接使用参数是行不通的。我还支持所有询问用户为什么要负责模式更改的人。这似乎是一个XY问题。“此外,为了防止SQL注入,您必须使用准备好的语句”-没有准备好的语句(大部分)阻止SQLi,但这不是唯一的解决方案。首先允许用户(非DBA、非开发人员、通常不受信任的用户)创建表有点奇怪。这里的用例是什么?同意,为什么用户会对架构有任何控制权?@但在准备好的语句中不能将窗口表名替换为值。@deceze-如果您查看OP提出的上一个问题,Raymond发表了一条评论,说明如何使用准备好的语句创建名称来自用户输入的表。不过,解决方案并非万无一失。但是,您是对的,在语句中直接使用参数是行不通的。我还支持所有询问用户为什么要负责模式更改的人。这似乎是一个XY问题。“另外,为了防止SQL注入,您必须使用预处理语句”-没有预处理语句(大部分)会阻止SQLi,但这不是唯一的解决方案。+1而且需要回勾,因为regexp允许一个空格,并且不会阻止表名成为保留的SQL关键字。@Bill Karwin。谢谢你的建议+1另外,由于regexp允许一个空格,并且不阻止表名成为保留的SQL关键字,所以必须使用反勾号。@Bill Karwin。谢谢你的建议!