PDA

View Full Version : PHP/SQL Injection question - apostrophes automatically escaped?


ThunderPoit
2010-03-16, 16:57
I am working through Head First PHP / MySQL. In a chapter dealing with PHP security, they demonstrate SQL injection and how to protect against it. I have tried to do the SQL injection on my script (same example script from the book) but cannot get the injected code to do anything, asside from get inserted into my database. From what i can see, it looks like the apostrophes are automatically escaped with a \
Is this some setting thats enabled in my php build, or am I doing something wrong with the injection?
The script is at http://example.com if anyone wants to try anything on it. I have a table named kill_me in that same database. I tried '); drop table kill_me; -- in the user name field and then put in a bs score and img, but nothing happened.

chucker
2010-03-16, 17:14
Show your PHP code?

What does your book say about how to protect? Does it suggest escaping (not advisable unless unavoidable), or parameterization?

http://bobby-tables.com/php.html

!Marc!
2010-03-16, 17:48
One thing to check is that you dont have the 'magic quotes' feature turned on, as this will automatically escape the injection code and it will be just inserted into your db as you are experiencing.

ThunderPoit
2010-03-16, 17:48
I'll post the code then I get to something that isn't an iPhone. I should clarify, I have done nothing in the way of security to protect the script. But if I type any apostrophes in the input fields, they seem to get escaped before they have a chance to mess with my database

ThunderPoit
2010-03-16, 17:51
One thing to check is that you dont have the 'magic quotes' feature turned on, as this will automatically escape the injection code and it will be just inserted into your db as you are experiencing.

That sounds like what I am seeing. I'll turn it off and try again.

Brad
2010-03-16, 18:32
If you ever find yourself concatenating strings with user-input values to run as SQL, you're Doing It Wrong™. :)

Always always always use some some of abstraction library (PHP probably has some built-in; if not then try out ADOdb) that will do variable binding for you. That way you never have to worry about manually patching special conditions for quotes, etc. Smart people have already solved this problem long ago; rely on their solutions.

Example with ADOdb:

$sql = 'INSERT INTO my_great_table VALUES (?, ?, ?)';
$binds = array($value1, $value2, $value3);
$db->Execute($sql, $binds);

!Marc!
2010-03-16, 18:42
If you ever find yourself concatenating strings with user-input values to run as SQL, you're Doing It Wrong™. :)

Always always always use some some of abstraction library (PHP probably has some built-in; if not then try out ADOdb) that will do variable binding for you. That way you never have to worry about manually patching special conditions for quotes, etc. Smart people have already solved this problem long ago; rely on their solutions.

Example with ADOdb:

The built in PDO abstraction library does exactly that too.

ThunderPoit
2010-03-16, 21:53
ok, magic quotes disabled, but now if i try to SQL inject, it just gets completely ignored, weird.

Here's my script. I'm aware that this script has all sorts of security problems, this is the script before they show you how to prevent attacks.

<html>
<head>
<title>Guitar Wars - Add Your High Score</title>
<link rel="stylesheet" type="text/cass" href="style.css" />
</head>
<body>
<h2>Guitar Wars - Add Your High Score</h2>

<?php
//Define the uplaode path and max file size constraints
require_once('appvars.php');

if (isset($_POST['submit']))
{
// Grab the score data from the POST
$name = $_POST['name'];
$score = $_POST['score'];
$screenshot = $_FILES['screenshot']['name'];
$screenshot_type = $_FILES['screenshot']['type'];
$screenshot_size = $_FILES['screenshot']['size'];
if (!empty($name) && !empty($score))
{
if ((($screenshot_type == 'image/gif') || ($screenshot_type == 'image/jpeg') ||
($screenshot_type == 'image/pjpeg') || ($screenshot_type == 'image/png')) && ($screenshot_size > 0) &&
($screenshot_size <= GW_MAXFILESIZE))
{
if ($_FILES['file']['error'] == 0)
{
// Move the file to the target upload folder
$target = GW_UPLOADPATH . $screenshot;
if (move_uploaded_file($_FILES['screenshot']['tmp_name'], $target))
{
// Connect to the database
$dbc = mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME );

// Write the data to the database
$query = "INSERT INTO guitarwars VALUES (0, NOW(), '$name', '$score', '$screenshot')";
mysqli_query($dbc,$query);

//Confirm sucess qith the user
echo '<p>Thanks for adding your new high score!</p>';
echo '<p><strong>Name:</strong>' . $name . '<br />';
echo '<p><strong>Score:</strong>' . $score . '<br />';
echo '<img src="' . GW_UPLOADPATH . $screenshot . '" alt="Score Image" /></p>';
echo '<p><a href="index.php">&lt;&lt; Back to high scores</a></p>';

// Clear the score data to clear the form
$name = "";
$score = "";

mysqli_close($dbc);
}
else
{
echo '<p class="error">Sorry, there was a problem uploading your screenshot image.</p>';
}
}
}
else
{
echo '<p class="error">The screenshot must be a GIF, JPEG, or PNG image file no greater than ' . (GW_MAXFILESIZE / 1024) . 'KB in size.</p>';
echo '<p>Name: </p>' . $screenshot .
'<p>Type: </p>' . $screenshot_type .
'<p>Size: </p>' . $screenshot_size;
}
// Try to delete the temporary screen shot image file
@unlink($_FILES['screenshot']['tmp_name']);
}
else
{
echo '<p class="error">Please enter all of the information to add your high score.</p>';
}
}
?>

<hr />
<form enctype="multipart/form-data" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<label for="name">Name:</label>
<input type="text" id="name" name="name" value="<?php if (!empty($name)) { echo $name; } ?>" />
<br />
<label for="score">Score:</label>
<input type="text" id="score" name="score" value="<?php if (!empty($score)) { echo $score; } ?>" />
<br />
<label for="screenshot">Screen Shot:</label>
<input type="hidden" name="MAX_FILE_SIZE" value="32768" />
<input type="file" id="screenshot" name="screenshot" />
<hr />
<input type="submit" value="Add" name="submit" />
</form>
</body>
</html>

!Marc!
2010-03-17, 16:32
// Write the data to the database
$query = "INSERT INTO guitarwars VALUES (0, NOW(), '$name', '$score', '$screenshot')";
mysqli_query($dbc,$query);


Are you sure the first value should be 0? This would normally be a primary key, so they cant all be 0.

chucker
2010-03-17, 16:40
// Write the data to the database
$query = "INSERT INTO guitarwars VALUES (0, NOW(), '$name', '$score', '$screenshot')";
mysqli_query($dbc,$query);


Are you sure the first value should be 0? This would normally be a primary key, so they cant all be 0.

Assuming this is in fact a primary key, and that it's an auto-increment integer column: I think MySQL has some convention by which you can insert 0 and it will treat that as "new".

ThunderPoit
2010-03-17, 16:40
The 0 is dropped in place of the auto-incremented ID field.
I have the page set to echo out the query after the page is submitted, and when i copy the entire query and paste it in a terminal, it works fine, but when used as sql injection, does nothing.

!Marc!
2010-03-17, 16:53
Assuming this is in fact a primary key, and that it's an auto-increment integer column: I think MySQL has some convention by which you can insert 0 and it will treat that as "new".

well I didn't know that :)