在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查询浏览器注入到网页,它会有所作为吗?感谢...
答案 0 :(得分:2)
是的,这是安全的。 (编辑:不,不是)
关键是要知道SQL文本何时被分析并转换为语义树。准备好的语句就是:准备好的语句,只是等待参数。它们存储在完全编译到内部执行计划的服务器中,缺少参数的“漏洞”。
这就是为什么你得到语法错误,你试图将整个WHERE部分设置为参数;但它是一个完整的表达树。准备好的语句只能有数据元素的“漏洞”,而不能用于语法文本。
传递参数的协议是完全二进制安全的,无论你在参数变量中有什么,它们都将作为二进制数据发送并仅用作数据,而不是作为SQL命令的一部分。
修改强> 哎呀!我刚刚注意到你正在进行文本插值,不是在PHP中而是在SQL中。这意味着您将在以后使用外部数据构建SQL命令。
绝对不安全。
答案 1 :(得分:1)
由于其中一个值来自用户,因此可以使用某些形式的SQL注入;虽然只能运行SELECT查询,但仍可以通过将1=1
传递给页面来显示信息。以这种方式显示的信息的实际有用性可能很低,但仍然可能发生。
答案 2 :(得分:1)
任何时候将值插入到语句中都有注入的可能性。该程序很脆弱。 SQL过程和函数中注入的唯一一般限制是PREPARE
适用于单个语句。在这种特定情况下,注入的文本在WHERE
中的SELECT
子句之后基本上限制了对子选择的攻击,UNION
,调用过程和函数(棘手但可能非常危险) ,并转储到文件(如果get_info
的定义者具有FILE
权限)。
举个例子,试试:
CALL get_info('tbl','1=0 UNION SELECT CONCAT(user, "@", host, " ", password) FROM mysql.user;');