I made a simple news system with comments using PHP and MySQL, and it worked great on my local Apache server, both on my Fedora 10 machine, and my Windows 7 one. Now I have a problem though, I uploaded it to a web host and it keeps returning all the ' and " as \' and \".
I believe this is either the web host who by automatic adds them for security reasons or that the MySQL is the wrong collation, but I have not been able to resolve it yet, testing multiple MySQL collations.
Here is a example of a query:
mysql_query("INSERT INTO news (title, poster, text, time) VALUES ('$newstitle', '1', '$newstext', '$time')") or die(mysql_error());
$time is time();
$newstitle and $newstext are parsed from $_POST and both are ran through mysql_real_escape_string() before I run the query (I guess this might be the problem, but since it is a part of the security I just don't want to remove it, and since it did not cause problems on my local servers)
As a final note: On my local apache servers I had latin1_swedish_ci which did not work on the web hosts server.
EDIT:
They look like this in the database:
\'\'\'\"\"\"
While on my local ones they didn't have the extra backslash, so it must be the PHP adding it. Is there any way to solve this except adding a function that removes extra backslashes?
These additional backslashes are probably Magic Quotes. Try to disable them or remove them before processing the data.
No, you don't want to run stripslashes(). Rather, set up your server properly.
First, turn off magic_quotes. This means that any data going into your script will have nothing escaped.
Then run mysql_real_escape_string() on the data, that'll add the slashes for the query only, and will store the data in the database without the slashes.
When you load the data again, you'll be good to go and there won't be any backslashes around the quotes.
Edit: As mentioned several times below, and in comments, the correct way to go about this is to disable magic quotes. Had I fully read and comprehended the question before replying, then that would probably have been better ;)
mysql_real_escape_string() will be doing what it says, and escaping the relevant characters within the string. Escaping quotes is done by prefixing them with the escape character (a back-slash in PHP, and many other languages). When you pull the data back from the database, do something like run stripslashes() (see the PHP doc) on the content, to remove the slashes from things like quotes.
Edit: As Gumbo mentioned, it could also be due to Magic Quotes being enabled on the server. You should disable these as per his answer.
Take a look at your magic_quotes settings, and compare them on your servers. Your home servers probably have magic_quotes disabled (as they should be, since Magic Quotes is deprecated in current versions of PHP), and your web host likely has them enabled (which is sadly common). You can use:
<?php echo phpinfo(); ?>
for a quick comparison.
If magic_quotes is new to you, you may want to look into PHP security a bit more before you deploy anything you care about.
Questions containing "magic_quotes"
Your host might have Magic Quotes enabled.
Look at magic_quotes_gpc. You can turn this off via .htaccess and use mysql_real_escape_string().
The real solution is to use prepared statements in your insert queries.
Here's a site with an insert example right at the top.
Prepared Statements in PHP
The benefit is that it's a best practice, and the side-effect is that you no longer have to worry about cleansing the input against SQL injection attacks.
Related
I think it's strange that I can't find anything on this, but that's the case.
On my site, I allow users to enter text to be stored in my database. I use PDO to keep it safe, but then all of the dangerous characters have "\"s in front of them.
Is there an easy way to get rid of all that? Should I be using a different datatype in MySQL?
Thanks in advance!
No double escaping. Laziness prevented it
I read that just doing straight PDO made it so you didn't have to worry about escaping, sanitizing, bleaching, scrubbing, etc...
I do the standard PDO INSERT like so How do I insert into PDO (sqllite3)?
The data is transmitted by jQuery ajax. Is that the source of the problem? If so, how do I reverse it?
Thanks for your help!
Specifics on problem
I have "\"s in front of quotes and double quotes only. Thanks!
Versions
PHP 5.3 for Zend Guard compatibility. MySQL 5.5. Apache 2.2.2. jQuery 1.8.3
+1 for reversal
I'll give as many +1s as answers on how to reverse these /'s. Thanks!
Magic Quotes
was the answer. Anyone want to lengthen their answer for check?
Still looking for a SQL statement to reverse previous escaping. Thanks!
This can be caused by having magic quotes enabled on the server. In particular, it's probably the magic_quotes_gpc directive, which can be set in php.ini, .htaccess, etc, but not at runtime with ini_set.
First, double-check the output of phpinfo() to be sure this is the problem. If you find that magic quotes is enabled, you'll need somebody with access to the server to disable it in your php.ini or .htaccess file. The php manual explains the process here: http://www.php.net/manual/en/security.magicquotes.disabling.php
Do be careful with this, though: If there is code running on the server that relies on magic quotes, disabling it could leave those sites vulnerable to attacks like sql injection.
You've obviously got some other escaping going on in your application before it hits the PDO layer. Look for addslashes or escape_string type method calls to see if you've got that going on.
What you're seeing is a sign of double escaping.
There is a (ugly)project I was asked to help with by doing a specific task.
The thing is, I don't have any control over the other files in the site much less over the server configuration. Some data I'm going to use comes from a query like this:
'SELECT * FROM table where value like "'.$unsafe.'"';
$unsafe is an unescaped value coming from $_POST or $_GET.
I checked the server, is PHP5.1.6 and has magic_quotes_gpc On so the data is being auto escaped.
Is this query breakable? Being $unsafe between colons gives me the impression It cant be broken but maybe I'm missing something.
I know magic_quotes_gpc is deprecated because of its insecurity so I'm concerned about it, not because of the application security which fails every where but for my own knowledge.
EDIT: I'm aware of the security implications of *magic_quotes_gpc* and I never use it in my own projects. I always use parameterized queries to avoid injection but this time I was asked to add a very specific pice of code in a friend/client project, so I cant change what is already done. I'd like to know if there is a specific value I can use to create an injection so I can illustrate my friend why he should change it.
if the DB is mysql use mysqli_real_escape_string() instead, if the PHP version is very old you can use the mysql_real_escape_string (not recommended at the moment).
even if the variable is between colons it can be injected, you just need to close the colons inside the value of the variable and then inject whatever you want afterwards.
With regard to your edit: You asked "I'd like to know if there is a specific value I can use to create an injection so I can illustrate my friend why he should change it."
According to the manual page for mysqli_real_escape_string(), the characters it escapes are as follows:
NUL (ASCII 0), \n, \r, \, ', ", and Control-Z.
The old mysql_real_escape_string() function also escapes the same characters.
This gives you a starting point as to which characters can be used to do injection attacks in MySQL. Magic quotes only escapes the quote characters and the slash character, which clearly leaves several gaping holes that can be exploited.
In an easy world, the above information would be enough for us to fix the escaping by doing a string replace on the remaining unescaped characters.
However, both the real_escape functions also require an active database connection for them to work, and this leads us to a further complication: character sets.
Further attacks are possible if the database has a different character set to PHP, particularly with variable-length character sets such as UTF-8 or UTF-16.
An attacker who knows (or can guess) the character set that PHP and the DB are using can send a crafted injection attack string that contains characters that PHP would not see as needing escaping, but which would still cause succeed in hacking MySQL. This is why the real_escape functions need to access the DB in order to know how to do the escaping.
Further resources:
Php & Sql Injection - UTF8 POC
SQL injection that gets around mysql_real_escape_string()
I hope that gives you a few pointers.
I'm working on a PHP comment system and came across the problem that the commentator's quotation marks are delimited when written to the comment file, so the output would end up like this for example:
"That is your father\'s! It\'s special to him!" (random sentence). How do I disable this?
The backslashes are added to the database query to prevent SQL injection. You can use the stripslashes() function to remove them when you retrieve the comments from the database.
You should also take a look at magic quotes.
It depends on version of PHP and it's configuration. Older versions (older than 5.3) had this enabled by default. It adds the quotes when you post your comment (so it will be stored in the database with the quotes). You can disable this behavior:
http://cz.php.net/manual/en/function.get-magic-quotes-gpc.php
http://cz.php.net/manual/en/function.set-magic-quotes-runtime.php
http://cz.php.net/manual/en/info.configuration.php#ini.magic-quotes-gpc
For existing comments, you'll have to run some cleanup script that will fetch all rows, performs stripslashes() on it and save it back.
Escaping your queries should be done by mysql_real_escape() anyway, relying on magic quotes is suicide, so if you think about it, it's safer to turn them off completely and escape the queries manually.
Turn gpc_magic_quote 's off in your php.ini .
Those backslashes are there to escape the quotation marks from the SQL engine.
That style of programming is quite common with the mysql_* series of functions which take a string directly from the program and execute it directly in the database engine. This is notoriously prone to SQL injection attacks and, as you've discovered, corrupting your data. (When applied consistently, you can always de-corrupt the data on the way back to the user, with the stripslashes() function, but that also must be done consistently.)
The far better approach in my humble opinion is to use prepared statements and let the database libraries insert data directly into the database without any escaping or un-escaping involved. This also completely removes the risk of SQL injection attacks. (Though you're still free to write insecure code.)
I've never programmed in an environment with magic quotes turned on before. Now I'm working on a project where it is. This is how I've been setting up user accepted data situations:
$first_name = $_POST['first_name']
if(!get_magic_quotes_gpc()) {
$first_name = mysql_real_escape_string($first_name);
}
With that filtering, am I still open for SQL injection attacks when magic quotes is enabled?
I'm really only concerned about any kind of SQL injection that will break my queries... Other whitelisting, htmlspecialchar() -ing etc. is in place for other areas.
Looking at some similar SO questions it seems that it's being advised to instead check for magic quotes, run 'stripslashes' on the data if it IS turned on, and then always run the escape function. I'm a little apprehensive to do it this way though because all of the existing code in the site assumes it's on.
Thanks!
Working with a legacy system can be a real PITA - especially with something like PHP which let some pretty egregious insecure code be written in the bad old days.
I think you've actually already answered part of your question:
Looking at some similar SO questions it seems that it's being advised to instead check for magic quotes, run 'stripslashes' on the data if it IS turned on, and then always run the escape function. I'm a little apprehensive to do it this way though because all of the existing code in the site assumes it's on.
I would also try and initiate a code review - find all places where use data is being written or used in database queries, and then replace with the more secure escaping. Eventually, you'll replace all of those squirrelly queries, and be able to turn magic quotes off for good.
If you use mysql_real_escape_string (correctly) there is no risk of SQL injection. That doesn't mean the input will be ok. If your magic quotes settings or any other stuff is set incorrectly, your variable may contain an incorrect value. It is still safe however.
magic_quotes_gpc
We all hate it and many servers still use this setting and knowingly enough some provides will argue it's safer but I must disagree.
The question I have is, what would a backslash be needed for?
I want to remove them completely which I can do but I am not sure if they are needed?
EDIT
Other then SQL injection.
magic_quotes_gpc() was provided based on the misguided notion that ALL data submitted to PHP from any external source would be immediately inserted into a database. If you wanted to send that data somewhere OTHER than a database, you had to remove the slashes that PHP just inserted, doubling the work required.
As well, not all databases use slashes for escaping metacharacters. \' is fine in MySQL, but in MS Access, escaping a single quote is actually '' - so not only was PHP doing unecessary work, in many situations, it was doing the work WRONG to begin with.
And then, on top of all that, addslashes (which is basically what magic_quotes_gpc() was calling internally) can't handle all forms of SQL injection attacks, particularly where Unicode is used. addslashes is a glorified form of str_replace("'", "\\'", $string), which works at the ASCII level - plenty of Unicode sequences can look like regular ascii, but get turned into SQL metacharacters after a simplistic addslashes() has wreaked its havoc.
They are for preventing SQL injection exploits, a very serious issue you should read up on if you're going to be coding for the web.
You should look into prepared queries, which is a much better way of avoiding SQL injection.
There is no good reason to have this feature in PHP.
That's why it's officially deprecated and will not exist in future versions.
If there were good reasons to keep it, the developer community would have done so.
They are designed to make us do extra work to remove them. For example, some code in Dokuwiki.
Don't forget about magic_quotes_runtime too.