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.
上一篇: SQL注入预防使用错误页面