views:

803

answers:

6

Hey everyone,

I'm quite frustrated. I want to be able to insert into my database names with single quotes - for example, O'Connor.

So, when inserting into the DB, I do:

 $lname = mysql_real_escape_string($_POST['lname']);

And then I insert $lname into the DB.

When it's in the DB, it appears as O\'Connor.

So, if I were to recall that last name in my web application, I will have to use:

 $lname = stripslashes($r["lname"]);

This all seems to work fine. However, I have a search function which will search for last names and display the results. When I search, I have to search for O\'Connor in order to get any results.

You see, after I search, the textbox automatically stores the value of what was just searched for (using sessions). So my code is this:

 $search = mysql_real_escape_string($_GET['search']);
 $_SESSION['search'] = $search;

Like I said before, when I search, I have to use "O\'Connor", and then after I search, the value in the textbox becomes "O\\\\'Connor"

It's been frustrating trying to figure this out. Does anyone know what I'm doing wrong? Thanks!

EDIT:

Here is my php5.ini file, regarding magic quotes:

 ; Magic quotes
 ;

 ; Magic quotes for incoming GET/POST/Cookie data.
 magic_quotes_gpc = On

 ; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
 magic_quotes_runtime = Off

 ; Use Sybase-style magic quotes (escape ' with '' instead of \').
 magic_quotes_sybase = Off

However, my site is hosted on GoDaddy, and I do not have permissions to edit the file :(

A: 

All you need to do is take the search query, mysql_real_escape_string it, and it should be perfectly fine. The best way to do this though is to never store it escaped, and instead just escape it everything is goes into the database.

Instead, do this:

 $_SESSION['search'] = $_GET['search'];
 $search = mysql_real_escape_string($_GET['search']);
Chacha102
+4  A: 

It sounds like Magic Quotes are enabled in your PHP configuration.

To check if it's actually enabled:

echo get_magic_quotes_gpc();

To disable, edit your php.ini file:

; Magic quotes
;

; Magic quotes for incoming GET/POST/Cookie data.
magic_quotes_gpc = Off

; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
magic_quotes_runtime = Off

; Use Sybase-style magic quotes (escape ' with '' instead of \').
magic_quotes_sybase = Off

Or add this line to your .htaccess:

php_flag magic_quotes_gpc Off
jimyi
He doesn't have magic quotes on, he is just escaping an escaped value.
Chacha102
I don't see where he is escaping twice. To me, it seems like $_POST['lname'] is already escaped, so adding it to the DB after calling mysql_real_escape_string will store it in its escaped state.
jimyi
Please see my EDIT. It seems that magic quotes are on, but I cannot edit the php.ini file because it is hosted on GoDaddy...
behrk2
As I see it, he is showing the escaped value in the Text Box and then saying that when he searches again, it escapes the escaped value. But, I might be wrong.
Chacha102
@behrk2 see my note about adding it to the .htaccess file. You should be able to do this. There's also one last option if you can't do that - see example #2 at http://us2.php.net/manual/en/security.magicquotes.disabling.php
jimyi
Thanks for your help, jimyi. I will try adding it to the .htaccess file. In the meanwhile, I was able to get things working by inserting O'Connor into the database without being escaped. But I'm guessing this is bad to do (b/c of SQL injections)? Also, are there applications that will just remove the single quote from the name entirely (if it's really not needed that much)?
behrk2
It's not bad because the purpose of magic quotes is to automatically escape for you. It's just not recommended to use because it's a deprecated feature and for the reasons here: http://us2.php.net/manual/en/security.magicquotes.whynot.php .
jimyi
When I get echo get_magic_quotes_gpc(), it returns '1' both when I have added the line to .htaccess, and when I remove the line as well...
behrk2
@jimyi Scratch that - including the .htaccess file gives me a :Internal Server ErrorThe server encountered an internal error or misconfiguration and was unable to complete your request.When trying to access the site.
behrk2
A: 

Magic quotes are enabled. What this means is that anything placed in post or get or other similar locations is automatically escaped so that beginning programmers don't have to worry about it as much. It is deprecated in the current version of PHP, if I remember correctly.

What you want to do to deal with this, and have the script run the same from any configuration is the following:

function fixinput($value){
 if (get_magic_quotes_gpc()){
   $value = stripslashes($value);
 }

 return mysql_real_escape_string($value);
}

You may want to further modify this to wrap non-numeric data in quotes, which is a common variation, but I find it is better to place those quotes manually.

krdluzni
A: 

Little edit to the fixinput function to check if your installation of PHP does indeed have real escape string (older versions don't):

  function fixinput($value){
    if (get_magic_quotes_gpc()){
      $value = stripslashes($value);
    }

    if (function_exists('mysql_real_escape_string')) {
      return mysql_real_escape_string($value);
    }
    else {
      return mysql_escape_string($value);
    }
  }
Phil Rae
A: 

I dont check for get_magic_quotes_gpc is on/off.

I just do $lname = mysql_real_escape_string(stripslashes($_POST['lname'])); so if there is not any quoted text it wont strip slashes.. if there is quoted it will strip them off.

and it works wonders for me!

Wbdvlpr
Ok, but depending on the text used, this may transform the text the user submitted. In most cases it will work, but not all. Also, it may just be that you have always been on an environment where magic quotes is on, in which case you wouldn't have any trouble (until you try to port it to another environment).
krdluzni
@kdluzni .. wtf? I wrote that it works wonders for me (and it means may not work "wonders" for everyone" .. and I also mentioned i dont check for get_magic.. because I know that it is ON.
Wbdvlpr
Yes, but just saying you don't check without explaining why may lead to the OP believing something is always safe when it isn't. If your environment works with this, that's great, but the method can have pitfalls and it's important to point them out. Furthermore, magic_quotes are deprecated, and will be removed as of PHP 6. At that time, your code will stop working correctly, while code that checks the gpc will work fine (until they someday remove the check function, but it doesn't sound like they plan to).
krdluzni
A: 

When it's in the DB, it appears as O\'Connor.

So, if I were to recall that last name in my web application, I will have to use:

 $lname = stripslashes($r["lname"]);

Wrong! When you escape strings with mysql_real_escape_string, they are only escaped in the query. The database interprets the query, so the data ends up in the database without any escape-characters. You do not have to use stripslashes when pulling data out of the database. If you think you do, then it means that the data in your database is mangled. Most likely because you have magic quotes turned on.

You should:

  • Turn off magic quotes or reverse their effect globally. See the manual for details.
  • Either use bound parameters (The best solution) or escape all variables with mysql_real_escape_string. You should do this where you are building the query.
  • Not do anything on the stuff you pull out from the database.

In particular, do not make a function a la the fixinput and variants that is listed in some of the answers here. It is the wrong way to solve the problem, because it will mess up any data that doesn't come from a http-request.

troelskn
Only if you use it on data that you shouldn't. Saying not to use a function to simplify making data safe before sending it to the db is equivalent to saying you shouldn't write a function for validating phone numbers, but should place that code manually every time you expect one. Or write any other functions to shorten and clarify your code. The point of a function is using it where it should be used, not everywhere. If you were to end up with mangled data from using the function, that only means you've used it in a place it doesn't belong.
krdluzni
I disagree. It's a bad abstraction because it does two disparate things in the same place. It is much better to fix the problem than to paint it over with a weak abstraction. It's also badly named, which means that the chance of misuse or confusion is high.
troelskn
I'll admit the naming could use some work, but it only does one thing. It handles input. You use it on any data that the user has had the chance to manipulate before sending it to the query.As for fixing the problem, that is definitely a better solution when it is possible, but having personally experienced the difficulties brought on from not controlling your host environment, I prefer to write code that will work independently of such settings (even though they are disabled on my own system). I think of it as not using windows- or unix-only commands/headers/libraries when writing in C.
krdluzni
You don't need to control php.ini to reverse magic quotes. See the manual that I linked to above.
troelskn