存储过程中的准备好的语句是否安全,不受SQL注入的影响?
在MySQL中是一个在SQL注入安全的存储过程中的准备语句? 见下面的例子。 get_info存储过程传递一个表名(pTbl)和where子句(pWhere)。 p可以有多个AND(例如fld1 =“a”AND fld2 =“b”AND ...)。 这可能不是最好的办法,但我需要动态SQL。
CREATE PROCEDURE get_info(pTbl VARCHAR(10), pWhere TEXT)
BEGIN
SET @uSQL = CONCAT('SELECT info FROM ',pTbl,' WHERE ',pWhere);
PREPARE ps FROM @uSQL;
EXECUTE ps;
END$$
我尝试使用MySQL查询浏览器调用像下面这样的存储过程,但只是收到了一个错误,说我的SQL中有一个语法错误。
CALL get_info('tbl','1=1;SELECT * FROM information_schema.TABLES;');
如果它有助于任何使用PDO从PHP调用存储过程,如下所示。 $ tbl是$ _SESSION变量,$ whr是$ _GET变量。
$s=$c->prepare("CALL get_info(?,?)");
$s->execute(array($tbl,$whr));
这个存储过程安全吗? 如果不是,我将如何注入它? 如果我从MySQL查询浏览器vs网页注入,它有什么不同吗? 谢谢...
任何时候你在一个语句中插入一个值都有注入的可能性。 该程序很脆弱。 在SQL过程和函数中注入的唯一一般限制是PREPARE
在单个语句上工作。 在这种特定情况下,注入的文本在SELECT
的WHERE
子句之后基本上限制了对子选择, UNION
,调用过程和函数(棘手但可能非常危险)的攻击以及转储到文件(如果get_info
的定义者FILE
权限)。
作为例子,请尝试:
CALL get_info('tbl','1=0 UNION SELECT CONCAT(user, "@", host, " ", password) FROM mysql.user;');
是的,这是安全的。 (编辑:不,不是)
关键是要知道什么时候分析了SQL文本并将其转换为语义树。 准备好的陈述恰恰是:准备好的陈述,只是等待论据。 它们存储在完全编译为内部执行计划的服务器中,缺少参数的“漏洞”。
这就是为什么你得到语法错误,你试图将整个WHERE部分设置为一个参数; 但它是一个完整的表达式树。 准备好的陈述只能有数据元素的“漏洞”,而不能用于语法文本。
传输参数的协议完全是二进制安全的,不管你在参数变量中有什么,它们都将作为二进制数据发送并仅用作数据,而不是作为SQL命令的一部分。
编辑 ooops! 我刚刚注意到你正在进行文本插值,只是不在PHP中,而是在SQL中。 这意味着您稍后使用外部数据构建SQL命令。
绝对不安全。
由于其中一个值来自用户,因此可能会使用某些形式的SQL注入; 虽然只有SELECT查询可以运行,但仍可以通过将1=1
传递给页面来显示信息。 以这种方式显示的信息的实际用处可能很低,但它仍然可能发生。
上一篇: Is a prepared statement inside a stored procedure safe from SQL injection?
下一篇: Reference: What is a perfect code sample using the MySQL extension?