Stripslashes doesn't work for my magic-quotes in PHP - php

I have started using magic quotes and I have encountered a small problem, an easy problem I guess which I can't figure out.
I wan't to use striplashes which it does not remove when I write something in my textarea
Code:
<?php
echo "Removed Slashes: ";
// Remove those slashes
if(get_magic_quotes_gpc())
echo stripslashes($_POST['question']);
else
echo $_POST['question'];
?>
<form method='post'>
Question: <input type='text' name='question'/><br />
<input type='submit'>
</form>
I also tried this one which actually works!:
<?php
$str = "Is your name O\'reilly?";
// Outputs: Is your name O'reilly?
echo stripslashes($str);
?>
But now I want to use my input for the website for secutiry reasons

I cant put it any better than this comment by cHao on the manual page
The very reason magic quotes are deprecated is that a one-size-fits-all approach to escaping/quoting is wrongheaded and downright dangerous. Different types of content have different special chars and different ways of escaping them, and what works in one tends to have side effects elsewhere. Any sample code, here or anywhere else, that pretends to work like magic quotes --or does a similar conversion for HTML, SQL, or anything else for that matter -- is similarly wrongheaded and similarly dangerous.
Magic quotes are not for security. They never have been. It's a convenience thing -- they exist so a PHP noob can fumble along and eventually write some mysql queries that kinda work, without having to learn about escaping/quoting data properly. They prevent a few accidental syntax errors, as is their job. But they won't stop a malicious and semi-knowledgeable attacker from trashing the PHP noob's database. And that poor noob may never even know how or why his database is now gone, because magic quotes (or his spiffy "i'm gonna escape everything" function) gave him a false sense of security. He never had to learn how to really handle untrusted input.
Data should be escaped where you need it escaped, and for the domain in which it will be used. (mysql_real_escape_string -- NOT addslashes! -- for MySQL (and that's only unless you have a clue and use prepared statements), htmlentities or htmlspecialchars for HTML, etc.) Anything else is doomed to failure.
Really, take the advice. Don't use them, you won't learn anything useful by trying them out, just forget they ever existed.
Take a look at this article http://www.sitepoint.com/magic-quotes-headaches and this one http://econsultancy.com/us/blog/2663-web-app-security-basics-filtering-input-and-escaping-output for more information.

Well it's easy to attack but seemingly more effort to help. So here's my attempt at being helpful.
So, you are posting data back to the server and you want to ensure that whatever the user posts back does not end up somewhere that it can act maliciously.
The naive strategy you have adopted it to say ok, I'll sanitise data generically by turning on the magic quoting, which should escape all of the nasties...
However, it doesn't. Your job is to ensure that you use a custom sanitisation strategy when dealing with untrusted data, depending completely on how you use it. A good resource for learning where you should allow untrusted data to enter a particular location, and how to escape untrusted data can be found at OWASP
You'll notice that not all locations are suitable for untrusted data, escaped or otherwise. This highlights the fact that to truly implement secure websites you have to consider both where untrusted data is going and how data is getting there.
This question is more directly focussing on the how, because we are considering (and attacking the use of) a generic escaping mechanism. You are implying that turning on magic quotes is a suitable method for escaping data destined to all locations your untrusted data can end up.
Best practice says that actually, you need to use an escaping mechanism that is suitable for the location(s) you intend to use it. As has already been pointed out, the use of mysql_real_escape_string is a popular function which is specific to escaping strings for use in a MySQL query. People do use this mechanism, but the need to manually escape your data with this mechanism is superceded by the correct use of PHP Data Objects (PDO). (Binding your untrusted data to a parameter rather than manually building up query strings).
Other obvious escaping mechanisms include encoding html characters using htmlspecialchars or htmlentities and, the more generic quote escaping mechanisms addslashes and addcslashes. There are even escaping methods for command line arguments escapeshellarg and escapeshellcmd
So you can see that escaping data properly is far less trivial than applying magic quotes to all of your incoming data, and there are often well established mechanisms for escaping data safely depending on the location you intend to use it.

Easy fix to your problem is to create a simple function that you push all your data through if it is going to be touching your DB. Can be modeled as such:
function sanitizeString($var)
{
$var = strip_tags($var);
$var = htmlentities($var);
$var = stripslashes($var);
return mysql_real_escape_string($var);
}//end sanitizeString

Related

Sanitizing both HTML and SQL at once?

Right now I am using htmlspecialchars(mysql_escape_string($value)), but is there a way to sanitize it with one statement rather than a nested statement?
Well there's no one function that handles both of them.
You can use prepared statements and html puffier class, maybe then the "look and feel" will be little bit better :)
mysql_real_escape_string has actually fallen out of favor lately.
It is now preferred to use PDO or mysqli. They both come with PHP by default. They use something called parameterized queries to access the database, rather than having you write the SQL command yourself. This means that you don't need to worry about escaping anymore, since the query and the variables are passed into the function separately.
You can learn more about PDO here:
http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/
On a related note, it is conventional to store user-supplied input into the database "as it was written", rather than using htmlspecialchars. You should then use htmlspecialchars to escape the data wherever the it appears on the site. This is a convention recommended by OWASP.
This is because you need to escape different things depending on context. This string:
' <script src="http://example.org/malice.js"></script> ]}\\\\--
...will need to be treated differently if it is used as a parameter in JSON (the quotes and backslashes and ] and } need to be escaped), HTML (the quotes and <s need to be escaped), or written as a URL (almost everything needs to be escaped). If you need to spend time instructing your JavaScript to un-encode the HTML, then your code is going to be confusing quickly.
This approach also makes fixing bugs simpler: if your site has a bug where content isn't escaped properly on a single page, then you can update the page and everything is fixed. If your site has a bug where the data is getting stored in the database incorrectly, then you need to fix everything in the database (which will take much longer and harm more users).

Do I really need to use mysql_real_escape_string when I save data in the DB?

I am using mysql_real_escape_string to save content in my mySQL database. The content I save is HTML through a form. I delete and re-upload the PHP file that writes in DB when I need it.
To display correctly my HTML input I use stripslashes()
In other case, when I insert it without mysql_real_escape_string, I do not use stripslashes() on the output.
What is your opinion? Does stripslashes affect performance badly ?
Do not use stripslashes(). It is utterly useless in terms of security, and there's no added benefit. This practice came from the dark ages of "magic quotes", a thing of the past that has been eliminated in the next PHP version.
Instead, only filter input:
string: mysql_real_escape_string($data)
integers: (int)$data
floats: (float)$data
boolean: isset($data) && $data
The output is a different matter. If you are storing HTML, you need to filter HTML against javascript.
Edit: If you have to do stripslashes() for the output to look correctly, than most probably you have magic quotes turned on. Some CMS even made the grave mistake to do their own magic quotes (eg: Wordpress). Always filter as I advised above, turn off magic quotes, and you should be fine.
Do not think about performance, think about security. Use mysql_real_escape_string everytime you're inserting data into DB
No, don't escape it. Use prepared statements instead. Store your data in its raw format, and process it as necessary for display - for example, use a suitable method to prevent Javascript from executing when displaying user supplied HTML.
See Bill Karwin's Sql Injection Myths and Fallacies talk and slides for more information on this subject.
See HTML Purifier and htmlspecialchars for a couple of approaches to filter your HTML for output.
Check out a database abstraction library that does all this and more for you automatically, such as ADOdb at http://adodb.sourceforge.net/
It addresses a lot of the concerns others have brought up such as security / parameterization. I doubt any performance saved is worth the developer hassle to do all this manually every query, or the security practices sacrificed.
It is always best to scrub your data for potential malicious or overlooked special characters which might throw errors or corrupt your database.
Per PHP docs, it even says "If this function is not used to escape data, the query is vulnerable to SQL Injection Attacks."

How to secure $_REQUEST?

How can I secure $_REQUEST before inserting to mysql database? For example following:
$message = $message = $_REQUEST['message'];
$tags = $_REQUEST['item']['tags'];
Thanks.
Depends on what you mean by "secure", and how you intend to insert the data. $_REQUEST isn't broken or anything; it's just that the data in it can be just about anything, so you'll need to "sanitize" it before you use it.
For example, if 'some_id' should only ever be an int,
$some_id = intval($_REQUEST['some_id']);
will ensure that $some_id is always an int. (Even if it didn't exist in $_REQUEST! In which case it will be 0.)
If you use prepared statements, a lot of the issues with $_REQUEST data go away -- that is, extensions like PDO and mysqli will escape parameters for you (if you use placeholders, like all good prepared statements should!), so all you have to do is make sure the data is valid. (For example, above, it'd have been a good idea to make sure $_REQUEST['some_id'] was set first -- since we didn't, we got a 0 back, which may not be valid.)
If you don't use prepared statements, then you have a little more work ahead of you. You'll need to use mysql_real_escape_string to escape strings as you feed them into the database, like so:
$some_string_sql = mysql_real_escape_string($_REQUEST['some_string']);
$id = intval($_REQUEST['id']);
mysql_query("UPDATE stuff SET some_string = '$some_string_sql' WHERE id = $id");
Note that i did this just for the query! Too many PHP noobs think they can just apply some magic formula to everything in $_REQUEST at the beginning of their script to make everything safe. You kinda can, if you're always just feeding it directly into an SQL query -- but it trashes your data if you're using it for other stuff! For example, if you write the data to a file as well, blindly escaping the data will leave you with a bunch of ugly backslashes in your file. You should never have to *un*escape your data -- it should always be escaped as you need it, for the specific purpose you intend to use it. (htmlentities for arbitrary data being printed to the screen, mysql_real_escape_string for stuff going into an SQL query.)
Also note: If you have magic_quotes_gpc enabled on your site, disable it for the reasons mentioned in the previous paragraph. Properly escaped stuff will break in the presence of magic quotes, because it's already been "escaped" once (half-assedly, hence the quotes) by PHP! Fortunately this misfeature will be removed from PHP 6, if it ever ships. But til then, if you have magic quotes enabled, you'll need to stripslashes(anything from $_REQUEST, $_GET, $_POST, or $_COOKIE) before you can properly escape it. DO NOT rely on the magic quotes -- they're a convenience thing, and not at all designed for security.
You should just not forget escaping your data when injecting them in some SQL queries.
Either use a function to escape the data :
Depending on the API you're working with :
mysql_real_escape_string,
mysqli_real_escape_string,
or PDO::quote
Or you could use Prepared Statements :
Those might seem a bit harder to understand, at first -- but they are worth investing sometime...
With mysqli,
And with PDO.
Then, of course, when using the data from the database to generate some output, the same idea applies : escape the output.
If you are generating some HTML output, you'll typically want to use something like htmlspecialchars.
Or, to allow some specific HTML tags, see HTML Purifier.
If you are generating some other kind of output, you'll have to find how to escape your data specifically for this type of output.
Use either mysql_real_escape_string() or PDO's prepared statements. I recommend the latter, as it also helps keep your queries nice and tidy.
As secure as anything could be in them.
The user can change those values to whatever they want.
So, not secure at all. Always sanitize your inputs.
There is nothing to secure.
Your database input should be just properly formatted.
For the strings it's quoting and escaping.
As long as your input data is limited to strings and you follow formatting rules, no special security required.

PHP secure user variable

On my website I have a variable called $user_data that contains input from a form. I then show this variable on the user page (via echo).
What is the best method to avoid any security risks with this variable? I use strip_tags(), but it is not enough.
This variable also gets saved to a MySQL database.
There are two very important things you must do to avoid serious security problems.
You need to escape the user input before putting it in your SQL query. Escaping means escape all the special characters such as '; luckily, there is a function that already does it automatically: mysql_real_escape_string.
If you don't escape user input nasty things could happen. Imagine that your query is INSERT INTO userdata VALUES ('$user_data'). Now imagine that the user wrote '; DROP DATABASE userdata;.
If you don't escape it, your query will become: INSERT INTO userdata VALUES (''; DROP DATABASE userdata;'). As you can imagine this is not good: if you have multi statements enabled you can kiss goodbye to your database. This is called an SQL Injection attack.
When you are outputting your variable to the user you also need to properly replace HTML special characters with HTML entities. Luckily, there is a function to do that too: htmlspecialchars(). It will transform the special HTML characters such as < to <.
This seems to be a problem that is often underestimated, but in reality it's very serious. Imagine if $user_data contains <script>SomeNastyScript()</script>. It could exploit existing vulnerabilities in the browser of your users, or it could send a non-HTTPOnly cookie (that may contain saved passwords) to the attacker, or it could trick the user into writing their password on a form generated through the manipulation of the DOM (possible in javascript), or a lot of other bad things.
This is called XSS (Cross-site scripting).
Short version
Call mysql_real_escape_string on the string before inserting it into your SQL query (but not when you echo it).
Call htmlspecialchars on the string before displaying it to the user (but not when you put it in the database).
When you're going to output something, strip_tags or htmlspecialchars is fine. I prefer the latter, since you then don't totally destroy <3 and the like that were never meant as HTML tags anyway.
When putting a value directly into a query, mysql_real_escape_string is the appropriate way to escape, or just using PDO and prepared statements.
Of course, it's best to do these escape methods only when you're about to need them, rather than applying both to all variables ever. It's always a pain to have to strip the slashes back out of a MySQL-escaped variable if you want to actually work with it before putting it into the database, and that's no better than PHP4's magic quotes. Similarly, you don't want to turn someone's password of "one<two" into "one<two" before inserting it into the database. (Obviously, you shouldn't be storing plaintext passwords, but the generic example stands.)
There is not a thing called "secureness".
No way to just secure an abstract variable. Everything depends on the scenario.
A condoms commonly used for safety. Would you secure your money with a condom? I suppose - no.
Same here.
You'd better distinguish these 2 matters - a database security and displaying security.
Database one is little more complicated than just "Call mysql_real_escape_string". I've described all the rules comprehensively in this answer
You can also do this:
$way = preg_replace('#[^a-z0-9]#i', '',
strip_tags(htmlentities(htmlspecialchars(mysqli_escape_string($db_conx, $_GET['way'])))));

Understanding input escaping in PHP

One thing that's always confused me is input escaping and whether or not you're protected from attacks like SQL injection.
Say I have a form which sends data using HTTP POST to a PHP file. I type the following in an input field and submit the form:
"Hello", said Jimmy O'Toole.
If you print/echo the input on the PHP page that receives this POST data, it comes out as:
\"Hello\", said Jimmy O\'Toole.
This is the point where it gets confusing. If I put this input string into (My)SQL and execute it, it'll go into the database fine (since quotes are escaped), but would that stop SQL injection?
If I take the input string and call something like mysqli real_escape_string on it, it comes out like this:
\\"Hello\\", said Jimmy O\\'Toole.
So when it goes into the database via (My)SQL, it ends up as:
\"Hello\", said Jimmy O\'Toole.
This obviously has too many slashes.
So if the input comes through HTTP POST as escaped, do you have to escape it again to make it safe for (My)SQL? Or am I just not seeing something obvious here?
Thanks in advance for any help.
Ah, the wonders of magic quotes. It is making those unnecessary escapes from your POST forms. You should disable (or neutralize) them, and many of your headaches go away.
Here's an exemplary article of the subject: http://www.sitepoint.com/blogs/2005/03/02/magic-quotes-headaches/
Recap: disable magic quotes, use real_escape_string().
Instead of relying on escaping I would use parametrized SQL queries and let the mysql driver do whatever escaping it needs.
It looks like your PHP server has the Magic Quotes feature enabled - that's where your first set of slashes comes from. In theory, it should then be unnecessary to call the escape functions - but when the app runs on a server with magic quotes disabled, you're suddenly wide open to SQL injection while thinking you aren't.
As chakrit wrote, escaping is not the best way to protect yourself - It's much safer to user parameterized queries.
What's going on is that you have Magic Quotes turned on in your PHP configuration.
It's highly recommended that youturn magic quotes off - in fact, they've been removed from PHP 6 completely.
Once you disable magic quotes, you'll see the POSTed text coming back exactly as you typed it in to the form: "Hello", said Jimmy O'Toole.
It's now obvious that you need to use the mysql escaping functions or even better, prepared statements (with prepared statements you can't forget to escape a string as it's done for you).
Obvious is the keyword for a hacker.
I think escaping normally should be enough, but protecting against just the quotes might not be enough.
See this SQL Injection cheatsheet, it's a good list of test you can run and see if too many slahses is a good thing or not.
And don't forget to escape other kinds of values too, i.e. numeric fields and datetime fields can all be injected just as easily as strings.

Categories