Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apparently there is an SQL injection bug in my PHP code

include "../admin/site.php"; // Setup db connection.

$appid = -1;
if (is_string($_GET["id"]))
{
    $id = mysql_real_escape_string($_GET["id"]);
    $sql = "select * from version where id=$id";
    $ver = mysql_query($sql);
    if ($id > 0 && $ver && mysql_num_rows($ver))
    {
        $appid = mysql_result($ver, 0, "AppID");
        $app = DLookUp("apps", "name", "id=$appid");
        $name = mysql_result($ver, 0, "Name");
        $notes = mysql_result($ver, 0, "Notes");
    }
    else $app = "No version by that ID";
}
else $app = "No ID";

/* some html snipped */

if (isset($app) && isset($name))
    echo $app . " v" . $name;
else
    echo "v###";

/* some html snipped */

if (isset($appid))
{
    $url = "/" . DLookUp("apps", "Page", "id=$appid");
    echo "<a href=\"$url\">Up</a> to $app...";
}
if (isset($notes))
    echo $notes;

Somehow this code is allowing someone to see the entire contents of my database. I would've thought that mysql_real_escape_string would prevent that sort of attack? I could cast $id to an integer which should fix the issue, but I want to understand what I did wrong here, so I don't keep repeating my mistake.

like image 501
fret Avatar asked Dec 22 '22 05:12

fret


2 Answers

I think part of the problem is that you aren't using quotes around $id, so an attacker may send a value for id that is 1 OR 1=1 and the SQL executed would be:

select * from version where id=1 OR 1=1

mysql_real_escape_string() escapes just NULLs, newlines, and quotes (\x00, \n, \r, \, ', " and \x1a), so it is of little help if you don't quote the variable.

like image 127
Elias Dorneles Avatar answered Dec 24 '22 01:12

Elias Dorneles


You (at least) need to quote the $id even the column is an integer

select * from version where id="{$id}"

But, if the supply $_GET["id"] using

$id = "xxx\" OR 1=1";
select * from version where id="{$id}" <-- this become a vulnerable 
as it eval to
select * from version where id="xxx" OR 1=1

You should consider bind the parameter :

select * from version where id :=id

Or at least doing the casting to integer $id = (int)$_GET["id"],
you are suppose to compare to integer column, aren't you?
(force it to zero when the $_GET["id"] is not an integer)

Take a look on this :-

  • Someone has hacked my database - how?
  • Does mysql_real_escape_string() FULLY protect against SQL injection?

And always enclose the database link identifier when dealing with mysql_* function
(you might have multiple database connections in a single page)

like image 28
ajreal Avatar answered Dec 24 '22 02:12

ajreal