It is said that in order to prevent from SQL injection one should filter the input data eg. with addslashes or mysql_real_escape_string depending on used connection modules
However, data escaped with addslashes is being saved into the database WITH the slashes, so a user surname would save as O\'Reilly instead O'Reilly. The one needs to use stripslashes to display it correctly.
So how do I use addslashes and save into the database without slashes? Is it actually the way it should be done?
You DONT use addslashes you use the appropriate DB specific escaping function like mysql_real_escape_string.
if you are using PDO then using a prepared statement will escape the variables as part of binding process. In this case all you need to do is something like:
$pdo = new PDO($dsn, $user, $name);
$stmt = $pdo->prepare('INSERT INTO your_table (col1, col2,col3) VALUES (?, ?, ?)');
$stmt->execute(array('value 1', 'value 2', 'value 3');
OR for extra readability and esier reuse you can use named params:
$pdo = new PDO($dsn, $user, $name);
$stmt = $pdo->prepare('INSERT INTO your_table (col1, col2,col3) VALUES (:col1, :col2, :col3)');
$stmt->execute(array(':col1' =>'value 1', ':col2' =>'value 2', ':col3' =>'value 3');
addslashes is supposed to be a one-size-fits-all escaping mechanism. If you MySQL-escape an addslash-escaped strings, of course the value including the addslash slashes will be saved to the database. Use either or, not both.
Having said that, don't use addslashes. It serves no real purpose. Use the specific escaping mechanism for the appropriate situation. I.e., only use mysql_real_escape_string. Or prepared statements, which avoids the whole escaping mess to begin with.
If you use prepared statements (via PDO or the mysqli library, for instance,) you don't need to escape or filter anything.
Related
I have this php pdo:
try {
$STH = $db->prepare("INSERT INTO racuni (napomene) VALUES (:12)");
$STH->bindParam(':12', $_POST['napomena'], PDO::PARAM_STR);
} catch (PDOException $e) {
echo $e->getMessage();
}
and now when I try to add this data to mysql:
<script>alert('heheheheheheh')</script>
there is no string escapes? And in database I have the same data:<script>alert('heheheheheheh')</script>
SO,
What is the best, safe way to insert data to mysql using php pdo?
When retrieving values from the database, you need to treat those values as if they are unsafe, as if they might include HTML special characters, or might contain javascript.
To get that value displayed safely in a web page, you need to run that value through a proper escaping mechanism.
PHP provides the htmlentities function to do just that, replacing HTML special characters with suitable replacements. As an example:
$val = htmlentitites("<script>alert('heheheheheheh')</script>");
Would assign something like this to $val
<script>alert('heheheheheheh')</script>
(It might also replace some other characters.) But the end result is if you put that string out on a web page, what you are going to "see" displayed on the web page appears like the original string. That string won't be interpreted as javascript.
Bottom line, you can't assume that because a string is being returned from the database that it's "safe". You must treat it as potentially unsafe.
Does PDO "sanitize" input?
In a word, NO. PDO doesn't sanitize values in SQL statements to remove HTML special characters or other potentially unsafe values.
What the prepared statement with the bind placeholder does is ensure that the value supplied in the statement gets passed into the database, without being interpreted as SQL text.
As an example, using PDO prepared statement with bind placeholder
$sql='INSERT INTO tab (col) VALUES (:val)';
$sth=$db->prepare($sql);
$sth->bindParam(':val', $value);
$sth->execute();
vs. incorporating the value into the SQL statement
$sql = "INSERT INTO tab (col) VALUES ('" ,. $value ."')";
$db->query($sql);
Consider what happens in each case when $value contains this string
foo'); DROP TABLE tab; --
With the first pattern (prepared statement with bind placeholder), that string value gets passed to the database, and stored in the column.
In the second example, incorporating that value into the text of the SQL statement, we get potentially dangerous SQL statements submitted:
INSERT INTO tab (col) VALUES ('foo'); DROP TABLE tab; --')
This an example of what SQL Injection vulnerability is about. And this demonstrates why using prepared statements with bind placeholders thwarts SQL Injection, it defends against a whole swath of nastiness that can happen when we don't treat values as potentially unsafe.
If $value contains the string:
<script>alert('heheheheheheh')</script>
With the prepared statement and bind placeholder, that's the value that's going to be stored in the database. It's just a string. It won't be interpreted as part of the SQL statement.
We can get the same thing to happen with the other pattern, that's vulnerable to SQL Injection, if we use double quotes instead of single quotes around the string literal in our SQL, e.g.
INSERT INTO tab (col) VALUES ("<script>alert('heheheheheheh')</script>")
Or, if we used an "escape string" function
INSERT INTO tab (col) VALUES ('<script>alert(''heheheheheheh'')</script>')
Again, that string gets stored in the database, because it's a valid string. It doesn't matter one whit whether that's got HTML special characters in it.
Bottom line, PDO does not sanitize HTML characters in strings. Your code needs to handle all values returned from the database as if they are potentially unsafe, and run them through the htmlentities or a similar function to "disarm" the values from being interpreted e.g. as javascript.
Using prepared statements is best, which is what you're doing (assuming you're executing the statement (not in your code sample)). Prepared statements escape values to prevent SQL injection, not cross-site scripting.
The value is unchanged entering the database, which is good (IMO). You should filter the values when you output them if needed (for example, htmlentities()).
You can also bind params in the execute method:
$STH = $db->prepare("INSERT INTO racuni (napomene) VALUES (?)");
$STH->execute(array($_POST['napomena']));
First you need to tell PDO to throw exceptions as bellow:
$pdo = new PDO("mysql:host={$dbhost};dbname={$dbname}", $dbuser, $dbpass);
// add this:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Now wrap your database operations in a try - catch block:
try
{
$statement = $pdo->prepare("INSERT INTO racuni (napomene) VALUES (:12)");
$statement->bindParam(':12', $_POST['napomena'], PDO::PARAM_STR);
// etc.
$statement->execute();
}
catch ( PDOException $exception )
{
echo "PDO error :" . $exception->getMessage();
}
I am trying to avoid SQL injection in my page.
// Connect to database server and select database
$connection = new PDO("mysql:dbname=tt8888;host=mysql.tt8888.com", "tt8888", "ttnopassword");
// Quote data to prevent SQL injection
$name = $connection->quote($name);
// Insert now
$connection->query("INSERT INTO Contact (name, eeeee, llll, mmmmm, iiiii) VALUES ('$name','$eeeee','$llll','$mmmmm','$iiiii');");
Without quote(), it inserts just fine. And using print $name;, the quote() part seems work fine. Why is there nothing inserted into database after using quote()?
PDO::quote will put single quotes around your values. So you don't need to do that yourself in your SQL.
Though I'd strongly recommend you switch to using prepare() with named parameters.
Do not use PDO::quote. It is much better to use parameterized queries.
$stmt = $connection->prepare("INSERT INTO Contact (name, e, l, m, i) VALUES (?,
?, ?, ?, ?)");
// This will quote all of the values for you
$stmt->execute(array($name, $eeeee, $llll, $mmmm, $iiiii));
You can also use bind methods (bindParam or bindValue) instead of passing the arguments directly to execute. This will allow you to specify the data types if it's necessary, but it seems like these are all supposed to be strings.
I'm having troubles with an insert query with MySQL. Here's what I want to do:
in one of the fields in my table, I want to insert a bunch of URLs and their respective titles. I build up this query like so:
?content=<title of webpage>%%<url of webpage>%%<title of webpage>%%<url of webpage>%%
and so on, depending how many URLs there are.
The problem is if the URL contains something like "?var=somevalue" then my query breaks there since MySQL will think that I am declaring a new variable.
How can I achieve this?
I think that you should escape the sequence with a \
If you are using PHP an option is to use the following command (it has multiple forms):
Procedural style
string mysqli_real_escape_string ( mysqli $link , string $escapestr )
Object oriented style
string mysqli::escape_string ( string $escapestr )
string mysqli::real_escape_string ( string $escapestr )
Here is how to use placeholders in PHP (which I suspect is the language you're using)
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);
$name = 'one';
$value = 1;
$stmt->execute();
I grabbed that from php.net
Placeholders, using prepared statements serve several functions, but one of them is to separate data from code safely so that the problem you're describing goes away.
Quoting from the site mentioned above:
The parameters to prepared statements
don't need to be quoted; the driver
automatically handles this. If an
application exclusively uses prepared
statements, the developer can be sure
that no SQL injection will occur
(however, if other portions of the
query are being built up with
unescaped input, SQL injection is
still possible).
I'm in the process of building a site with CodeIgniter. This is the 1st site that I've built myself that interacts with a database. I'm using MySQL for this project. How can I tell if data needs to be escaped before saving it to the database?
I would advice you to accustom yourself to use prepared statements. Especially since you are new to working with databases. The sooner you start using these, the easier it becomes a second nature.
I, for instance, didn't know about prepared statements when I started with databases. And I experienced my own stubborness when I came in touch with them. Because I had accustomed myself to another way of doing things already. Now, this might not be a character trade of yourself, but it doesn't hurt to start as soon as possible with it either way.
Prepared statements allow you to use placeholders in queries. These placeholders can then be substituted with actual values by binding them to the placeholders. This process of binding, automatically escapes the values.
Here's a (simple) PDO example:
$db = new PDO( /* some database parameters */ );
$statement = $db->prepare( 'INSERT INTO table VALUES( :username, :password )' );
$statement->bindValue( ':username', $dirtyUsername );
$statement->bindValue( ':password', $dirtyPassword );
$result = $statement->execute();
// result checking ommited for brevity
There's lot's more possibilities with PDO and prepared statements. For instance you can easily reuse the prepared statement in a loop, as such:
$statement = $db->prepare( 'INSERT INTO table VALUES( :username, :password )' );
foreach( $users as $dirtyUser )
{
$statement->bindValue( ':username', $dirtyUser->username );
$statement->bindValue( ':password', $dirtyUser->password );
$result = $statement->execute();
// result checking ommited for brevity
}
Or pass the placeholder bindings to the execute method, like so:
$statement = $db->prepare( 'INSERT INTO table VALUES( :username, :password )' );
$result = $statement->execute( array(
':username' => $dirtyUsername,
':password' => $dirtyPassword
) );
// result checking ommited for brevity
... etc., etc.
Don't worry about escaping yourself (you WILL screw it up). Use a DB layer where you prepare the statement first, and then add data to it.
In PHP you should use PDO. You write
SELECT * FROM table WHERE key = :key AND value = :value
and then add the data in by calling functions.
If you're using the database class with query bindings, you don't have to do any manual escaping:
The secondary benefit of using binds
is that the values are automatically
escaped, producing safer queries. You
don't have to remember to manually
escape data; the engine does it
automatically for you.
If the data is a string, it must always be escaped.
However, it's better to use parameters instead.
If you are generating SQL yourself rather than using something like PDO, then you must always escape strings.
Escaping strings is a basic requirement of the SQL language. It's what allows you to use characters like apostrophes or backslashes in a string without everything going bad. There is no situation at all in which escaping strings is not required.
Even non-strings will have to be filtered to ensure that they are, indeed, non-strings.
If you are learning, please seriously consider learning something like PDO as many others have said, rather than escaping your own strings.
When in doubt, escape it all. Can't be too safe.
Alright, alright. I get it
ALWAYS ESCAPE
You escape a MySQL query string when any of the string is made up of user input, for example:
in PHP:
$username = ;//VALUE FROM USER INPUT
then your query string is:
"INSERT INTO table ('username') VALUES (".$username.")"
You would have to escape this mySQL query due to the fact the $username variable could potentionally have malicous code inserted by the client to be injected into your database.
When to escape? As soon as your site goes public.
I use mysql_real_escape_string() to validate all user inputs before I insert them in a sql database. One of the fields is name, and we've had issues with users with names like O'Reilly. Is there any way to use mysql_real_escape_string() to block injections but allow these names in the db?
The problem is most likely that the apostrophes get quoted twice: first by the evil and deprecated in 5.3 magic quotes and then by mysql_real_escape_string().
What you can do is either disable magic quotes or run stripslashes() on your input values before feeding them to mysql_real_escape_string()
Brief explanation of the problem:
the user enters O'Reilly
magic quotes automatically turn it into O\'Reilly
the script feeds the string through mysql_real_escape_string() which escapes both the backslash and the apostrophe (again) yielding O\\\'Reilly
the query is executed, the quoting is processed and the database understands that you want a backslash and an apostrophe since they where both escaped, and records O\'Reilly
As already mentionned : mysql_real_escape_string is not meant for input validation. If you want to validate inputs, use your own functions or the filter functions from php.
If you have too many slashes added automatically by php, disable magic quotes.
To prevent SQL injection, use parameterized queries with either PDO or mysqli.
+1 for using PDO. I've been using PDO in favour of a MySQL class acting as a database abstraction layer for a few months now and it's a breeze.
Traditionally, developers would use the stripslashes() function on data before applying a function like mysql_real_escape_string(). It's still a good idea to remove slashes from input data, but you can then either use the PDO method for escaping data (PDO::quote($data)) or binding the parameter.
Your query block would then look something like this:
$pdo = new PDO(DSN, DB_USER, DB_PASS);
$sql = "INSERT INTO table (field1, field2) VALUES (:value1, :value2)";
$smt = $pdo->prepare($sql);
$smt->bindParam(':value1', $value1, PDO::PARAM_STR);
$smt->bindParam(':value2', $value2, PDO::PARAM_STR);
$smt->execute();
$rows = $smt->rowCount(); // returns number of rows affected
I hope this helps somewhat. Take a look at http://php.net/manual/en/book.pdo.php for more information on PDO in PHP.