I am totally confused, I've read a few posts but still I am not sure. I do not want to go the prepared statements route since this site is only on our intranet. I've read the following posts, but still I am uncertain.
When to use mysql_real_escape_string?
When to use mysql_real_escape_string()
My question: Should I use mysql-real-escape-string
When only I get user input from a form OR
On all my queries? eg: SELECT * FROM ......
For example in this post it states: You need to call this function when building SQL queries with string literals. You should not call it anywhere else.
What prepared statements do (among other things) is to call a method similar to mysql_real_escape_string()
If you don't use PDO, what is fine, you must understand what are you doing, and you will get the same security level.
The only and simple rule is all raw data needs mysql_real_escape_string() (or similar from other languages)
Examples are:
- Data from user input
- Data that you have stored RAW on DB (witch is the best way) and you are using on a new sql statment
- Data from unknow/other origin
The detalis are:
- be sure to not apply twice (to preserve data correctly)
Well I actually use it on :
ANY variable that I'm going to put into a MySQL Query and which could have been modified by a user, either if it's direct user input (through a form), or a parameter that I've been passing around via GET requests, etc
You get my point... :-)
It's important when you don't know for sure what's included in the string.
This means user inputs.
You might also want to consider moving to prepared statements with PDO.
You should use it on any variable that you are interpolating in a SQL query.
Everything that is not a literal string should be sanitized. It doesn't matter if you got it from a form, a database or anything else, if it's not constant then you should sanitize it.
The quoted sentence in your question is true.
All the other answers are wrong.
Every time you are going to add a quoted string to the SQL query, you have to always escape it.
That's the only case when you have to use mysql_real_escape_string().
PS. I can't believe this question is still alive with all it's answers.
Stackoverflow is a very strange place.
Related
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).
It's a well covered topic, but I'd like to get some confirmation on methods of using data from user variables, in a few different situations.
The variable is never used in a database, never stored, only displayed on screen for the user. Which function to use to make sure no html or javascript can screw things up?
The variable is taken into the database, and used in SQL queries.
The variable does both.
At the moment I xss_clean, and strip_tags. I've always done this, just by autopilot. Is there a better technique? Apologies if there's an identical question out there. I kinda assume there is, although I couldn't find one as thorough as this.
Cheers.
Use the appropriate function while outputting, in HTML context, this is htmlspecialchars
Use prepared statements
See 1. and 2. – depending on whether you are displaying the variable or you are using it in a query.
One of worst delusions in the PHP world is that $_GET or $_POST have anything to do with security.
It is not the source but destination that matters
If you have to deal with database, the rules always the same, no matter if the data is coming from $_POST, SOAP request or a database. It has to be ALWAYS the same: placeholders for the data, whitelisting for the everything else.
If you have to output some data into browser, you have to properly prepare it, no matter whether the data is coming from $_POST, SOAP request or a database.
If you have to read from a file - you have to secure the filename, no matter where it coming from, and so on
In the first case htmlspecialchars() probably is the best choice, allowing for users to use all characters like <, >, &, etc.
In the second case you will need to use some database escaping function like mysql_real_escape_string or a prepared statement with PDO or mysqli. Prepared statements are the best choice here but if you are only familiar with mysql then mysql_real_escape_string works fine too. If you are not using mysql then there are similar functions in most SQL APIs.
In the third case do both but separately, with gives you two diffrent results, one for output and one for database.
References:
http://php.net/manual/en/function.htmlspecialchars.php
http://php.net/manual/en/function.mysql-real-escape-string.php
http://php.net/manual/en/book.pdo.php
http://php.net/manual/en/book.mysqli.php
$id="1;drop table users;"; $id=mysql_real_escape_string($id); $sql="SELECT * FROM table
WHERE id=$id";
I'm trying to secure my script a bit after some suggestions in the last question I asked.
Do I need to secure things like $row['page_name'] with the mysql_real_escape_string function? example:
$pagename = mysql_real_escape_string($row['page_name']);
I'm asking mainly because when I do secure every row I get some errors like when trying number_format() it throws number_format() expects parameter 1 to be double, string given while when it is not secured with mysql_real_escape_string it works.
Can someone clear this for me? Do I only need to secure COOKIE's or the row fetches too?
I got the suggestion in this post: HERE (look at the selected answer)
You're doing it backwards. Presumably $row is a row coming out of the database. You don't mysql_real_escape_string on the way out of the database, you use it on data going into the database to prevent SQL injection. It prevents people from submitting data that contains executable SQL code.
Once the data is safely in the database, you're done with mysql_real_escape_string (until you attempt to update that data). User data coming out of the database needs to be run through htmlspecialchars before it hits the page to prevent script injection.
Basically, on the way to the database, just before your insert/update runs, you need to escape potentially executable SQL. On the way to the browser, just before strings leave your app for the browser, you need to escape potentially executable JavaScript and/or interpretable HTML. Escaping should be the last thing you do with a piece of data before it leaves your app for either the browser or database.
This is by no means a complete answer.
Before writing any more code you need to stop and consider exactly what it is you are trying to accomplish.
In other words, what are you gaining by running the mysql_real_escape_string function?
Generally speaking, you escape data submitted by the client. This is to help prevent sql injection. Also, you should go further to actually validate that what the client sent in is acceptable (ie. "Sanity Check"). For example, if you are expecting a numeric entry, don't accept strings and range check the values. If you are expecting string data like a name, don't accept HTML, but again range check to verify length is acceptable. Both of these situations occur when the client submits data, not when you are writing it back out.
Going a little further, your cookies should be encrypted and marked with the httponly flag to tell the browser that it is not for use in client side script. Even with that, you shouldn't trust the data in the cookie at all; so go ahead and run your sanity checks and still escape those values in queries.
I highly recommend that you go to the OWASP website and read through all of the issues to get a better understanding of how attacks work and how to defend against them. Web App security is too important to just start coding without really knowing what's going on.
BTW, kudos to you for learning about this and trying to defend your site. Too many devs don't even think about security at all.
If you use the PDO extension to build clean requests, you can create functions that will do this (secure strings and define their type) :
An exemple where $text is a string of text and $number is an integer :
public function InsertThis($number, $text) {
$pdo = $this->getPdo();
$sth = $pdo->prepare("INSERT INTO my_table (number, text) VALUES (:number, :text");
$sth->bindParam('number',$number,PDO::PARAM_INT);
$sth->bindParam('text',$text);
$sth->execute();
}
http://php.net/manual/en/book.pdo.php
You only need to use mysql_real_escape_string() when inserting/updating a row where the values have come from untrusted sources.
This includes things like:
$_GET
$_POST
$_COOKIE
Anything that comes from the browser
Etc..
You should only use it when putting things into the database, not when you are taking things out, as they should already be safe.
A safer way altogether is to use the PDO class
mysql_real_escape_string does not "secure" anything. It escapes characters that can be used in sql injection attacks. Therefore the only values that you should escape are the ones supplied by your users. There should be no need to escape things that come out of your own database.
On the PDO::Prepare page it states,
"and helps to prevent SQL injection attacks by eliminating the need to manually quote the parameters"
Knowing this, is there a PHP function like mysql_real_escape_string() that takes care of escaping stings for PDO? Or does PDO take care of all escaping for me?
EDIT
I realize now that I asked the wrong question. My question really was, "What all does PDO take care of for me?" Which I realize now with these answers that it really only removes the need to escape the quotes. But I would still need to do any other PHP sanitize calls on the values that I pass to the execute function. Such as htmlentities(), strip_tags()...etc...
PDO does not escape the variables. The variables and the SQL command are transferred independently over the MySQL connection. And the SQL tokenizer (parser) never looks at the values. Values are just copied verbatim into the database storage without the possibility of ever causing any harm. That's why there is no need to marshall the data with prepared statements.
Note that this is mostly a speed advantage. With mysql_real_escape_string() you first marshall your variables in PHP, then send an inefficient SQL command to the server, which has to costly segregate the actual SQL command from the values again. That's why it's often said that the security advantage is only implicit, not the primary reason for using PDO.
If you concat the SQL command and don't actually use prepared statments (not good!), then yes, there still is an escape function for PDO: $pdo->quote($string)
Very few people here understand what escaping is and when to use it.
Escaping itself does not make any data "safe". It just escapes delimiters, to distinguish a delimiter from a part of data. field = 'it's me' will cause an error, while field = 'it\'s me' will not. That's the only purpose of escaping. So, it works only when you use quotes. If you don't - escaping becomes useless.
Do you use quotes with placeholders? No. Thus, no escaping would be sensible.
When you are binding your variables, it works a very different way: it does not send the whole query to the server, but sends your prepared query separated from the bound data. So it cannot interfere. And thus makes no injection possible.
Yes and no:
Literals which you embed into the statement string need to be escaped as normal.
Values which you bind to the prepared statement are handled by the library.
If you prepare a statement and use bindParam or bindValue to supply variables, you do not need to escape the variables. Note that these functions assume that the variable contains a string, so use the third parameter to bindValue if you want to use booleans or floats.
You don't have to worry about it. PDO does not require you to escape your data before passing it along to the database.
Edit: Just to be clear, I mean to say that as long as you are passing variables into your parameters (for example, the value of a form field), you don't have to worry about it. However, if you're passing variables that you've defined as strings, for example, then obviously you need to escape anything that needs escaping in that string in order to avoid breaking syntax. However, this wouldn't even make much sense since one of the main advantages of PDO is that you're passing information from the user to the database without having to sanitize it yourself, and there aren't many times (if any?) that you would be passing strings that you yourself had defined.
Also, make sure you still sanitize your data for type. For example, make sure it's an integer if you expect it to be, make sure it's less than or greater than x if you expect it to be, etc.
I have a record edit link that GETs a 7 character alphanumeric text string which is always ZZZZ111 in structure and is then used in a MySQL query to pull all related data for that record id.
Is mysql_real_escape_string() all I need in terms of sanitizing this $_GET['id'] ? Or are there more steps to take to protect my database?
mysql_real_escape_string() will escape any malicious characters. In addition, you can use a regex like /^[A-Za-z]{4}\d{3}$/ to make sure that the user indeed entered a valid input.
To make input safe for an SQL query, mysql_real_escape_string() should be sufficient, though I suggest switching to PDO and prepared statements. They tend to be a little nicer to use, and a little more efficient (the statement is only parsed once, and the query can be re-used).
However, you also should make sure your pages are immune to cross-site scripting by (e.g.) filtering HTML from fields based on a whitelist.
If you plan on showing you data to users you would like to remove any HTML tags aswell. Maybe someone inserted a malicious javascript in a guestbook post for example?
this can be done with http://php.net/manual/en/function.htmlentities.php
Or you can use a inputfilter class to allow certain tags etc.
I found this one very useful http://www.phpclasses.org/browse/package/2189.html
mysql_real_escape_string() is a good start, and I would agree that using prepared statements would be a pretty good choice. Zend_Db is nice if you want to look into some DB abstraction which can make PDO easier to work with.
I'd also take this as an opportunity to write some sort of RegEx validator for your input. A sample regex that could get you started is:
[A-Z]{4}[0-9]{3}
More info on PHP and regex can be found here: http://www.regular-expressions.info/php.html
mysql_real_escape_string should do the job for $_GET['id']. Also, take a look at prepared statements via PDO.