What is the industry standard inserting user input that may contain apostrophes into a database? Such an input will be displayed back to users on a webpage. For example, a user updates some field to "I'm cool". I insert it into my database with this function:
public function updateDatabase($value) {
$value = mysql_real_escape_string($value);
Database::instance()->query(
'UPDATE myTable
SET myColumn = ' . $value . '
WHERE foo = "bar"'
);
}
The database will now store "I\'m cool". To display this value properly and safely back to any user, I would have to clean it with this function:
public function toSafeDisplay($userGeneratedValue) {
return stripslashes(
htmlentities(
$userGeneratedValue
)
);
}
My concern is that doing stripslashes and htmlentities on everything I want to display on a webpage will be very processor intensive. The general concensus on StackOverflow is to not do htmlentities before inserting into the database, so that the data is as raw as possible. This would allow it to be later displayed in any medium, not just websites. So we're forced to do htmlentities at display time. Is this also true with stripslashes? Or is it possible to remove all the slashes before the apostrophes before updating the database without introducing SQL injection attacks?.
That's not how it works at all. If you escape an apostrophy going into the insert/update when you read it back into php it will NOT be escaped. If you want HTML safe data coming out of the database then make it safe before you put it in.
Notice to developers that use mysql_real_escape_string properly:
If magic_quotes_gpc is enabled, first apply stripslashes() to the data. Using this function on data which has already been escaped will escape the data twice.
If you found out that magic_quotes_gpc is set to On turn it Off in php.ini!
Check also: http://gr.php.net/manual/en/function.mysql-real-escape-string.php
The database should not store it as I\'m cool, but rather as I'm cool. The escape is to allow the apostrophe to be included as part of the data updated in myColumn. I have seen cases where a site displays I\'m cool back to the user, but that is probably a case of double-escaping.
Edit:
mysql_real_escape_string does not store slashes in the database. It escapes the value in the SQL statement. The only way you would get extra slashes in the database is if you did something equivalent to mysql_real_escape_string(mysql_real_escape_string($value)).
Related
$string = "susan's"; //string is scraped from website
$string = html_entity_decode($string);
$sql = 'INSERT INTO database SET name = "'. $string .'"';
When I echo out $sql, it shows correct one: INSERT INTO database SET name="susan's", but when I run query it inserts susan's into database. When I run query manually from phpmyadmin it inserts correct one. Why do html entities get passed to database even when I remove them?
You need to use the ENT_QUOTES flag constant.
As per the manual:
https://secure.php.net/manual/en/function.htmlspecialchars-decode.php
ENT_QUOTES Will convert both double and single quotes.
A bitmask of one or more of the following flags, which specify how to handle quotes and which document type to use. The default is ENT_COMPAT | ENT_HTML401.
Where ENT_COMPAT produces susan's.
So your code ends up being:
$string = htmlspecialchars_decode($string, ENT_QUOTES);
Note: Depending on which API is used to insert this with, you need to be made aware that escaping it without using stripslashes() to it and should this be the case, may produce susan\'s, being another undesired result.
Use a prepared statement, should this be coming from user input if you're not already doing so.
https://en.wikipedia.org/wiki/Prepared_statement
This will help against an SQL injection.
https://en.wikipedia.org/wiki/SQL_injection
When I echo out $sql, it shows correct one: INSERT INTO database SET name="susan's",
Tip: Before inserting into your database, always look at your HTML source. That will reveal exactly what it is that is going to be passed in the query. That is also considered as being a "tool".
Echo and the (HTML) source are two different animals altogether.
I wrote a script to insert record in my DB. The only issue I am getting is when I try to store data which contains ' character then the script does not work and it does not store anything in the DB. For example John's Birthday , Amy's Home etc . Any solution to this problem which allows special character like ' to store in the DB and retrieving them without any harm to security?
mysqli_query($con,"INSERT INTO Story (desc)
VALUES ('$mytext')");
PHP's mysqli_real_escape_string is made specifically for this purpose. You problem is that quotes are being interpreted by MySQL as part of the query instead of values. You need to escape characters like this so they won't affect your query - this is what SQL injection is.
$mytext = mysqli_real_escape_string($con, $mytext);
// continue with your query
Manual: http://php.net/manual/en/mysqli.real-escape-string.php
Filter the variable part of the query through mysqli_real_escape_string.
I am using the code shown here, it uses addslashes() on the data fetched from the database before saving to file.
$row[$j] = addslashes($row[$j]);
My question is why and do I need to use this? I thought you would do this when saving to the database not the other way round. When I compare the results from the above script with the export from phpMyAdmin, the fields that contain serialized data are different. I would like to know if it would cause any problems when importing back into the database?
Script:
'a:2:{i:0;s:5:\"Hello\";i:1;s:5:\"World\";}'
phpMyAdmin Export:
'a:2:{i:0;s:5:"Hello";i:1;s:5:"World";}'
UPDATE
All data is escaped when inserting into the database.
Change from mysql to mysqli.
SQL file outputs like:
INSERT INTO test (foo, bar) VALUES (1, '\'single quotes\'\r\n\"double quotes\"\r\n\\back slashes\\\r\n/forward slashes/\r\n');
SOLUTION
Used $mysqli->real_escape_string() and not addslashes()
inserting to db
When inserting data to a MySQL database you should be either using prepared statements or the proper escape function like mysql_real_escape_string. addslashes has nothing to do with databases and should not be used. Escaping is used as a general term but actually covers a large number of operations. Here it seems two uses of escaping are being talked about:
Escaping dangerous values that could be inserted in to a database
Escaping string quotes to avoid broken strings
Most database escaping functions do a lot more than just escape quotes. They escape illegal characters and well as invisible characters like \0 ... this is because depending on the database you are using there are lots of ways of breaking an insert - not just by adding a closing quote.
Because someone seems to have missed my comment about mentioning PDO I will mention it again here. It is far better to use PDO or some other database abstraction system along with prepared statments, this is because you no longer have to worry about escaping your values.
outputting / dumping db values
In the mentioned backup your database script the original coder is using addslashes as a quick shorthand to make sure the outputted strings in the mysql dump are correctly formatted and wont break on re-insert. It has nothing to do with security.
selecting values from a db
Even if you escape your values on insert to the database, you will need to escape the quotes again when writing that data back in to any kind of export file that utilises strings. This is only because you wish to protect your strings so that they are properly formatted.
When inserting escaped data into a database, the 'escape sequences' used will be converted back to their original values. for example:
INSERT INTO table SET field = "my \"escaped\" value"
Once in the database the value will actually be:
my "escaped" value
So when you pull it back out of the database you will receive:
my "escaped" value
So when you need to place this in a formatted string/dump, a dump that will be read back in by a parser, you will need to do some kind of escaping to format it correctly:
$value_from_database = 'my "escaped" value';
echo '"' . $value_from_database . '"';
Will produce:
"my "escaped" value"
Which will break any normal string parser, so you need to do something like:
$value_from_database = 'my "escaped" value';
echo '"' . addslashes($value_from_database) . '"';
To produce:
"my \"escaped\" value"
However, if it were me I'd just target the double quote and escape:
$value_from_database = 'my "escaped" value';
echo '"' . str_replace('"', '\\"', $value_from_database) . '"';
I think you are mixing two problems. The first problem is SQL Injection and to prevent this you would have to escape the data going into the database. However by now there is a far more better way to do this. Using prepared statements and bound parameters. Example with PDO:
// setup a connection with the database
$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// run query
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = :name');
$stmt->execute(array(':name' => $name));
// get data
foreach ($stmt as $row) {
// do something with $row
}
The other thing you would have to worry about it XSS attacks which basically allows a possible attacker to inject code into your website. To prevent this you should always use htmlspecialchars() when displaying data with possible information you cannot trust:
echo htmlspecialchars($dataFromUnsafeSource, ENT_QUOTES, 'UTF-8');
All data is escaped when inserting into the database.
When using prepared statements and bound paramters this isn't needed anymore.
Should I use addslashes() then use str_replace() to change \" to "?
addslashes() sounds like a crappy way to prevent anything. So not needed AFAICT.
Another note about accessing the database and in the case you are still using the old mysql_* function:
They are no longer maintained and the community has begun the deprecation process. See the red box? Instead you should learn about prepared statements and use either PDO or MySQLi. If you can't decide, this article will help to choose. If you care to learn, here is a good PDO tutorial.
You should store data without modifying them.
You should perform the needed escaping when outputting the data or putting them "inside" other data, like inside a database query.
just use mysql_escape_string() instead of addslashes and ereg_replace as written in david walsh's blog.
just try it it'll be better. :)
I have a TextArea on my website which I write the input into my database.
I want to filter this TextArea input, but without removing any HTML tags or other stuff.
In short, I want to sanetize and securize the input before I write it into my database, but I want the entry to be intact and unmodified when I take back the entry from the database and write it on the website.
How can I achieve this?
If you want to preserve the data character for character when it's written back to the website try:
$stringToSave = mysql_real_escape_string($inputString);
Then when retrieving it from the database:
$stringToPutOnPage = htmlentities($databaseString);
If you want the html to actually be read as html (be careful about XSS) you can just use:
$stringToSave = mysql_real_escape_string($inputString);
Edit: It would seem that best practice is to sanitize the string for html after retrieving it from the database and not before. Thanks for the comments, I will have to change my method.
If you mean you simply want to make it safe to store in your database all you need to do is use the database specific escaping method, for example mysql_real_escape_string. Of course, that doesn't secure you from XSS attacks, but if you want to retrieve and display it unmodified you don't have a choice.
It's really simple:
To avoid SQL injection, mysql_real_escape_string your values before concatenating them into an SQL query, or use parameterized queries that don't suffer from malformed strings in the first place.
To avoid XSS problems and/or messed up HTML, HTML escape your values before plugging them into an HTML context.
JSON escape them in a JSON context, CSV escape them in a CSV context, etc pp.
All are the same problem, really. As a very simple example, to produce the string "test" (I want the quotes to be part of the string), I can't write the string literal $foo = ""test"". I have to escape the quotes within the quotes to make clear which quotes are supposed to end the string and which are part of the string: $foo = "\"test\"".
SQL injection, XSS problems and messed up HTML are all just a variation on this.
To plug a value that contains quotes into a query, you have the same problem as above:
$comment = "\"foo\""; // comment is "foo", including quotes
$query = 'INSERT INTO `db` (`comment`) VALUES ("' . $comment . '")';
// INSERT INTO `db` (`comment`) VALUES (""foo"")
That produces invalid syntax at best, SQL injection attacks at worst. Using mysql_real_escape_string avoids this:
$query = 'INSERT INTO `db` (`comment`) VALUES ("' . mysql_real_escape_string($comment) . '")';
// INSERT INTO `db` (`comment`) VALUES ("\"foo\"")
HTML escaping is exactly the same, just with different syntax issues.
You only need to escape your values in the right context using the right method. To escape values for HTML, use htmlentities. Do that at the time it's necessary. Don't prematurely or over-escape your values, only apply the appropriate escape function in the right context at the right time.
I am building a blog site and am having trouble with updating fields in my MYSQL database. Whenever I hit the update button on the form that uses PHP, it adds extra space before the text string in the MYSQL text field. Here is the PHP code:
//UPDATE TEXT
$updated_text = $_POST['text'.$the_post['ID'][$n]];
if ($updated_text != "") {
$sql = "UPDATE posts SET TEXT = '".addslashes($updated_text)."' WHERE ID = '".$the_post['ID'][$n]."'";
$text_result = mysql_query($sql) or die(mysql_error());
}
Thanks
Not sure why you have this problem, but you could first try using trim to remove white-characters at the beginning and end of your string :
$updated_text = trim($_POST['text'.$the_post['ID'][$n]]);
If this solves the problem, it's because you are receiving those whitespaces from the form -- else... Well, strange ^^
A couple of other notes :
When escaping data to send it to your DB server, yOu should use the functions that are specific to your DB. Here, you are working with a MySQL database, and the mysql_* function, which means you should use mysql_real_escape_string instead of addslashes.
You are escaping the data you're putting in the TEXT ; but, to avoid SQL injections, you should protect the data use in the where clause too.
If your ID is a char/varchar in DB, it means using mysql_real_escape_string on $the_post['ID'][$n] too
If your ID is an integer in database :
the quotes arround the value are not necessary : quotes, in SQL, are the string-delimiter ; there is no need for any delimiter for integers
you should make sure you are sending an integer to the DB ; for instance, using intval($the_post['ID'][$n])
This will not change anything about your problem -- but taking care of security is always best ;-)
Perhaps its an issue of the text-area tag of your html - for example if its indented or so..
I found that the empty mySQL field was inserting " " into my html form value, so I used:
$variable = trim($variable," ");
to trim the unwanted space.
If you have a space or line break (in your code editor) in between and then remove them. I had the same issue earlier, but is now fixed.