user975096
user975096

Reputation: 11

SQL Injection: is this secure?

I have this site with the following parameters:

http://www.example.com.com/pagination.php?page=4&order=comment_time&sc=desc

I use the values of each of the parameters as a value in a SQL query.

I am trying to test my application and ultimately hack my own application for learning purposes.

I'm trying to inject this statement:
http://www.example.com.com/pagination.php?page=4&order=comment_time&sc=desc' or 1=1 --

But It fails, and MySQL says this:

Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in /home/dir/public_html/pagination.php on line 132

Is my application completely free from SQL injection, or is it still possible?

EDIT: Is it possible for me to find a valid sql injection statement to input into one of the parameters of the URL?

Upvotes: 0

Views: 597

Answers (5)

Question Overflow
Question Overflow

Reputation: 11255

It really depends on how PHP validates those arguments. If MySQL is giving you a warning, it means that a hacker already passes through your first line of defence, which is your PHP script.

Use if(!preg_match('/^regex_pattern$/', $your_input)) to filter all your inputs before passing them to MySQL.

Upvotes: 0

Boann
Boann

Reputation: 50021

That's completely vulnerable, and the fact that you can cause a syntax error proves it.

There is no function to escape column names or order by directions. Those functions do not exist because it is bad style to expose the DB logic directly in the URL, because it makes the URLs dependent on changes to your database logic.

I'd suggest something like an array mapping the "order" parameter values to column names:

$order_cols = array(
    'time' => 'comment_time',
    'popular' => 'comment_score',
    ... and so on ...
);

if (!isset($order_cols[$_GET['order'])) {
    $_GET['order'] = 'time';
}
$order = $order_cols[$_GET['order']];

Restrict "sc" manually:

if ($_GET['sc'] == 'asc' || $_GET['sc'] == 'desc') {
    $order .= ' ' . $_GET['sc'];
} else {
    $order .= ' desc';
}

Then you're guaranteed safe to append that to the query, and the URL is not tied to the DB implementation.

Upvotes: 2

Sparky
Sparky

Reputation: 15085

I am assuming that your generated query does something like

select <some number of fields>
from <some table>
where sc=desc
order by comment_time

Now, if I were to attack the order by statement instead of the WHERE, I might be able to get some results... Imagine I added the following

comment_time; select top 5 * from sysobjects

the query being returned to your front end would be the top 5 rows from sysobjects, rather than the query you try to generated (depending a lot on the front end)...

Upvotes: 0

Doktor J
Doktor J

Reputation: 1118

I'm not 100% certain, but I'd say it still seems vulnerable to me -- the fact that it's accepting the single-quote (') as a delimiter and then generating an error off the subsequent injected code says to me that it's passing things it shouldn't on to MySQL.

Any data that could possibly be taken from somewhere other than your application itself should go through mysql_real_escape_string() first. This way the whole ' or 1=1 part gets passed as a value to MySQL... unless you're passing "sc" straight through for the sort order, such as

$sql = "SELECT * FROM foo WHERE page='{$_REQUEST['page']}' ORDER BY data {$_REQUEST['sc']}";

... which you also shouldn't be doing. Try something along these lines:

$page = mysql_real_escape_string($_REQUEST['page']);
if ($_REQUEST['sc'] == "desc")
  $sortorder = "DESC";
else
  $sortorder = "ASC";

$sql = "SELECT * FROM foo WHERE page='{$page}' ORDER BY data {$sortorder}";

I still couldn't say it's TOTALLY injection-proof, but it's definitely more robust.

Upvotes: 0

zerkms
zerkms

Reputation: 254916

The application secured from sql injection never produces invalid queries.

So obviously you still have some issues.

Well-written application for any input produces valid and expected output.

Upvotes: 2

Related Questions