Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this MySQLI prepared statement allow SQL injection?

As I was teaching students how to prevent SQL injection today, I was mildly embarrassed. In professional projects I've used prepared statements / parameterized queries as one layer of prevention against SQL injection (although I've never used mySQL professionally). In theory, I thought SQL injection was impossible when using a prepared statement.

But then this worked...

$Search = $_GET['s'];
$stmt = $mysqli->prepare("SELECT * FROM products WHERE id = ?");
$stmt->bind_param("i", $Search);
$stmt->execute();
$Results = $stmt->get_result();

If I pass the parameter "?s=1 OR 1=1" then I can get a full listing of all products. I still can't insert another query at the end, but I am confused about why this type of basic SQL injection is possible in mysql/php. I assumed that the parameter "1 OR 1=1" would be rejected because it isn't numeric (obviously I could run that numeric check ...).

Can anyone explain why this works, and what I don't understand about prepared statements in php/mysql?

My school computer has an out-of-the-box Zend WAMP installation btw.

EDIT: This is the string value that is causing my confusion:

$Search = "1 OR 1=1";
like image 880
Paul Morel Avatar asked Nov 07 '13 21:11

Paul Morel


People also ask

Does Mysqli prepare prevent SQL injection?

If implemented correctly, prepared statements (aka parameterized queries) offer superior protection against SQL injection. You basically just create the query template with placeholder values, and then replace the dummy inputs with the real ones.

Is SQL injection possible with prepared statements?

Prepared statements are very useful against SQL injections, because parameter values, which are transmitted later using a different protocol, need not be correctly escaped. If the original statement template is not derived from external input, SQL injection cannot occur.

How can SQL injection be prevented?

The only sure way to prevent SQL Injection attacks is input validation and parametrized queries including prepared statements. The application code should never use the input directly. The developer must sanitize all input, not only web form inputs such as login forms.

Which of the following should be used to defend against SQL injection?

Developers can prevent SQL Injection vulnerabilities in web applications by utilizing parameterized database queries with bound, typed parameters and careful use of parameterized stored procedures in the database. This can be accomplished in a variety of programming languages including Java, . NET, PHP, and more.


1 Answers

That's ok, no any kind of SQL injection here, you do not see list of all products (at least code you provided cannot show it)

you do not need to cast to int, lets go deeper what bind_param actually do:

it has string "i" which means 1 integer argument

you're passing value from $_GET which is string

bind_param tries to convert String to int, so check this php code:

echo intval('a', 10); // output 0
echo intval('1a', 10); // output 1
echo intval('12a', 10); // output 12
echo intval('b1', 10); // output 0
echo intval('1 or 1=1', 10); // output 1
echo intval("?s=1 OR 1=1", 10); // output 0

so, you output products with id=1, maybe you have some of them?

like image 106
Iłya Bursov Avatar answered Oct 13 '22 00:10

Iłya Bursov