在服务器端转义字符串

时间:2015-12-21 18:18:17

标签: mysql sql escaping

我在数据库中有一个存储过程,它接受直接插入查询的字符串参数。我有客户端代码来逃避输入,但这并没有阻止任何有权使用错误参数执行该过程并注入SQL的人。

目前的实施是这样的:

CREATE PROCEDURE grantPermissionSuffix (perm VARCHAR(30), target VARCHAR(30), id VARCHAR(8), host VARCHAR(45), suffix VARCHAR(45))
BEGIN
  SET @setPermissionCmd = CONCAT('GRANT ', perm, ' ON ', target, ' TO ''', id, '''@''', host, ''' ', suffix, ';');
  PREPARE setPermissionStmt FROM @setPermissionCmd;
  EXECUTE setPermissionStmt;
  DEALLOCATE PREPARE setPermissionStmt;
  FLUSH PRIVILEGES;
END
显然,这是灾难的一个方法。如何防止注射机会?是否有标准的SQL函数来逃避输入? MySQL有一个吗?是否有另一种方法可以在没有额外客户端代码的情况下获得相同的结果?

我担心唯一的解决方案是客户端准备好的陈述,目前不是一种选择。我需要在服务器上处理所有逻辑,要求客户端只调用此过程(我不想授予用户直接修改表/权限的权限,只能通过他们的程序处理它)。允许执行)。

1 个答案:

答案 0 :(得分:0)

您可以使用?占位符为变量和稍后EXECUTE USING变量准备语句,就像在客户端预准备语句中一样,至少根据manual。我不确定在替换表名时这会有多好,但是这受到prepare规则的限制,所以如果它不在服务器端工作,那么它就不会这样做。也可以在客户端工作。

<强>更新

显然,mysql不会在准备好的?查询中识别GRANT个占位符。在这种情况下,您必须手动处理它。一些提示在that answer中 - 即使用`(反引号)来转义标识符并使​​用白名单作为关键字 - 这样,您还可以获得对您在程序中允许的内容的细粒度控制。

我想补充一点,为了您的特定目的,最好从information_schemamysql表中选择来控制它,例如,传递给您的db和table实际存在。您可以使用带有占位符的预准备语句,因此它是安全的。像这样的东西会检查db和table:

PREPARE mystat FROM 'SELECT count(*) into @res FROM INFORMATION_SCHEMA.TABLES WHERE upper(TABLE_SCHEMA)=UPPER(?) and UPPER(TABLE_NAME)=UPPER(?)';

set @db = 'mydb'; --these two are params to your procedure
set @table = 'mytable';
set @res = 0;
execute mystat using @db, @table;
select @res; --if it's still 0, then no db/table exists, possibly an attack is happening.

也可以使用mysql.users表来检查用户和主机。对于其他的参数,你必须建立一个白名单。

我看到的另一种方法是使用正则表达式检查允许的字符 - 那里有REGEXP命令。例如,您可以控制您的过程参数只有if @var REGEXP '^[A-z]+$'的字母大写。据我所知,仅使用A-z执行SQL注入是不可能的。