简体   繁体   中英

Why isn't this test SQL injection returning all rows in the table?

I was trying to follow this example on a local webpage I run using WAMP. Here is the code

<!DOCTYPE html>
<head>
    <title>Testing SQL injection</title>
</head>
<body>
<?php
$link = mysql_connect('localhost:3306', 'root', 'St@ck0verflow');
if(!$link)
    die('Could not connect: ' . mysql_error());
if(!mysql_select_db('opentarget', $link))//arguments are in revere order compared to mysqli
    die('Could not select database');
// a good user's name
$name = "Onetwo"; 
$query = "SELECT * FROM customers WHERE username = '$name'";
echo "Normal: " . $query . "<br />";
$result = mysql_query($query);
echo "Result: <pre>";
print_r(mysql_fetch_row($result));
echo "</pre><br /><br />";
// user input that uses SQL Injection
$name_bad = "' OR 1'"; 

// our MySQL query builder, however, not a very safe one
$query_bad = "SELECT * FROM customers WHERE username = '$name_bad'";
$result = mysql_query($query);
// display what the new query will look like, with injection
echo "Injection: " . $query_bad.'<br />Result: <pre>';
print_r(mysql_fetch_row($result));
echo '</pre>';
echo '<br />Any errors? '.mysql_errno($link) . ": " . mysql_error($link);
?>
</body>
</html>

The first query runs as expected but when I print the result of the second one it is the same as the first. I thought it would print out all the contents of the table? What exactly does OR 1 do?

I tried running the bad query directly in MySQL from the command line, and unless I'm doing something wrong I get the empty set (which is different than the results displayed in PHP).

$query_bad = "SELECT * FROM customers WHERE username = '$name_bad'";
$result = mysql_query($query);

See how your SQL string variable is different to the variable you put in the query function? You are building $query_bad but passing $query to the mysql_query() function.

OR 1 Always evaluates to true because 1=TRUE in PHP.

So basically it is trying to show you what happens when someone puts bad text into some piece of data you are using in a query...

Your original query was

SELECT * FROM customers WHERE username = '$name'

But that name variable might be set to this phrase:

' OR 1'

So you just piece those together and will see that instead of returning just the username you want, SQL will return and username that is a) '' [blank], or b) Anything (Because each time 1=TRUE so the row is returned).

EDITED - Added below line to help clarify

To simplify this better, imagine the sql server looking for data. It will look at each row and run that WHERE statement. So it hits row 1 and asks does username = "harry"? . It will then return the row if this is true, or skip the row if it is false.

Now, Lets say you load $name from an input box on a web form. I might enter "Harry" or "Tom" or whatever. These are all valid. But what if I instead enter Harry' OR TRUE . On every row, SQL is asking Does username='Harry' OR TRUE Of course it probably evaluates Username=Harry to false, but the logical expression returns true because the second part is always true.

(0 OR 1) is always evaluated to TRUE.

I hope that helps clarify.

Also, check out this link to understand injection attacks better... http://www.unixwiz.net/techtips/sql-injection.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM