Is a prepared statement inside a stored procedure safe from SQL injection?

In MySQL is a prepared statement inside a stored procedure safe from SQL injection? See example below. The get_info stored procedure is passed a table name (pTbl) and the where clause (pWhere). pWhere can have many AND's (eg fld1="a" AND fld2="b" AND ...). It's probably not the best way to do it but I need to have dynamic 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$$

I tried calling the stored procedure like below using MySQL Query Browser but only got an error back saying I have a syntax error in my SQL.

CALL get_info('tbl','1=1;SELECT * FROM information_schema.TABLES;');

If it helps any the stored procedure is being called from PHP using PDO like below. $tbl is a $_SESSION variable and $whr is a $_GET variable.

$s=$c->prepare("CALL get_info(?,?)");
$s->execute(array($tbl,$whr));

Is this stored procedure safe? If not, how would I inject it? Does it make a difference if I inject from MySQL Query Browser vs from a web page? Thanks...


Any time you interpolate a value into a statement there's the possibility of injection. The procedure is vulnerable. The only general limitation with injection in SQL procedures and functions is that PREPARE works on a single statement. In this specific case, that the injected text is after a WHERE clause in a SELECT basically limits attacks to sub-selects, UNION , calling procedures and functions (tricky but potentially very dangerous), and dumping to files (if the definer of get_info has the FILE privilege).

As an example, try:

CALL get_info('tbl','1=0 UNION SELECT CONCAT(user, "@", host, " ", password) FROM mysql.user;');

Yes, it is safe. (edit: no, it's not)

The crucial point is to know when is the SQL text analyzed and transformed into the semantic tree. Prepared statements are precisely that: statements that are prepared, just waiting for the arguments. They're stored in the server fully compiled to the internal execution plan, with the 'holes' for the missing arguments.

That's why you're getting the syntax error, you're trying to set the whole WHERE part as an argument; but it's a whole expression tree. The prepared statement can only have 'holes' for data elements, not for syntactic text.

The protocol that transfers the arguments is fully binary safe, no matter what you have in your argument variables, they'll be send as binary data and used only as data, not as part of the SQL command.

edit ooops! i've just noticed that you are doing text interpolation, just not in PHP but in SQL. That means you're constructing the SQL command later, using external data.

definitely unsafe.


Since one of the values comes from the user, some forms of SQL injection are possible; while only SELECT queries can be run, it is still possible to reveal information by passing 1=1 to the page. The actual usefulness of the information revealed in this manner may be low, but it can still happen.

链接地址: http://www.djcxy.com/p/93702.html

上一篇: SQL注入预防使用错误页面

下一篇: 存储过程中的准备好的语句是否安全,不受SQL注入的影响?