When I post a variable to the database, of course, I use mysql_real_escape_string. This way special characters go in the database as it should.
When I read this variable out of the database, I use mysql_real_escape_string again together with stripslashes:
$var = stripslashes(mysql_real_escape_string($record['rowname']));
else it will give me slashes before quotes.
When I use this $var I mentioned above and want to echo it, I simple can echo "$var" because it has already been stripped and escaped, right?
And beside, if I use stripslashes + mysql_real_escape_string on a variable, then POST this same variable again in the database, is mysql_real_escape_string enough? Or do I need to stripslashes this variable again?
Summarized:
As I know how this works:
use mysql_real_escape EVERY time when using data with mysql: when reading query through variables just as posting variables to database.
Use stripslashes when echoing out escaped variables.
If you want to post stripslashes and escaped variables again to the database, you dont need to stripslash it again.
Do I miss htmlspecialchars?
EDIT
So this is all wrong?
while( $record=mysql_fetch_array($result) )
{
$custid=mysql_real_escape_string($record['custid']);
$custsurname=mysql_real_escape_string($record['custsurname']);
$custmidname=mysql_real_escape_string($record['custmidname']);
$custforename=mysql_real_escape_string($record['custforename']);
$custcountry=stripslashes(mysql_real_escape_string($record['custcountry'])); }
I'm afraid you're doing it wrong. The key point is that escaping is context sensitive and you completely disregard that fact.
On every data format, there're words or characters that are assigned special meanings in the format spec. For instance, a ' symbol in SQL means "string delimiter", a ? symbol in a URL means "start query string" and a < symbol in HTML means "start tag". You need escaping when you want to insert a literal word or character, i.e., you want to insert it as-is and remove its special meaning.
Once aware of that, it's clear that the syntax varies depending on the format and context. < means "start tag" in HTML but not in SQL or URLs. Thus you need to use a escaping method that's built for the target format and follows the format rules.
If you do mysql_real_escape_string() on data read from a database you're saying "escape my data so it can be injected as inside a SQL string". Your data gets ready to be used inside as a SQL string but get's corrupted for any other usage.
In this example, it happens that stripslashes() undoes most of what mysql_real_escape_string() did so you end up with an output that's basically unchanged. But that's pure chance.
Last but not least, having to escape database input parameters one by one is very annoying. All other DB extensions but the one you are using1 offer prepared statements. Don't get stuck with a deprecated extension that doesn't offer modern stuff.
1 Note: the legacy mysql extension has been deprecated for several years, when better alternatives became available, and it's no longer part of the language.
Update: a little clarification—escaping is just a syntax trick. You don't alter the input to the eyes of the target engine, which just sees the original data as-is. So there's no need to unescape the input when you retrieve it.
You don't need to stripslashes or mysql_real_escape_string the data coming from database, you just need to escape it before you query so the query parser knows what are special characters and what are literal characters.
stripslashes should be never used (as a hack to fix some symptoms), if you are going to need a variable after escaping it, use the original one:
$data_safe = mysql_real_escape_string( $data );
//$data can still be used normally
Escaping is only for a certain context, if the context is a mysql query then you will mysql real escape just for the query and nothing else. If the context is html output, then you will htmlescape just before outputting a string as html. At no point you want to actually modify the data itself. If you misunderstand this, you will see O\'Brian and O'Brian etc.
Related
We are developing a small website at school, so we were introduced to SQL injection in PHP and how to prevent it.
However I see most online examples and text books doing the following
$str = $_POST['user_input'];
$str = $mysqli->real_escape_string($str);
$str = htmlentities($str);
However I think the most logical way to validate input from users is:
$str = htmlentities($str);
$str = $mysqli->real_escape_string($str);
Does that make any difference for
Site accessibility (characters showed to end user, the string will just be "echoed" once retrieved from Database)
Preventing HTML and SQL injection (does wrong order allows injection?)
Performance of the server (for example one function is most expensive while the other increase string lenght, or just because the final string lenght is different and we want to save bytes on our Database)
?
Would be nice to cover also more escaping functions (maybe there is some dangerous combination/order that we should avoid).
I think that the right way is to search for escaping functions that outputs "dangerous characters" (dangerouse as HTML or as SQL, if any exist) and then just provide an input that generate those dangerous characters.
The order will result in different output.
The following code:
$string = 'Example " string';
echo htmlentities($mysqli->real_escape_string(($string))
. "\n"
. $mysqli->real_escape_string((htmlentities($string));
Results in:
Example \" string
Example " string
The output is different because if you escape the string before converting to HTML entities, it has a quote that needs escaping whereas if you do it in the reverse order the quote is replaced with the HTML entity and is a valid string value for MySQL.
That said, the two functions have entirely different purposes.
htmlentities is for converting strings to their HTML entities ready for output to a web browser.
real_escape_string is for converting a string for use between quotation marks in a MySQL query.
The two do not go together, you should store the text in the database (which will need escaping before being passed to) and convert to HTML entities when it comes to displaying it.
If you insist on storing the HTML entities version of the string in the database the correct way is to use htmlentities first, then escape it. Escaping of a string should be the last operation on it before passing to the database.
Doing it in the wrong way may result in stray backslashes as shown above, although when passed to MySQL these will actually be ignored as \& is not a valid escape sequence. You would only notice a difference if outputting the variable that was passed to the database (as opposed to later retrieving it from the database and then outputting it).
You may also want to look into prepared statements in mysqli:
http://www.php.net/manual/en/mysqli.prepare.php
I'm using codeigniter, and what I do is basically:
$val = $this->db->call_function('real_escape_string', $this->input->post('name'));
this is all I do on data before putting into database. And when someone enters value like O'hara, in database it will appear like O\'hara
So, I guess I can string slashes on output, but is this usual way of escaping and storing data in database?
SOLVED
Active Records escapes the query, so I do double escaping, with 'real_escape_string' function as well
So I guess I don't need to use real_escape_string at all, active records does this
The '\' is called an escape character and must be used so the next character after it (in your case ') won't interfere with the SQL statement. However, if you're using CI, it should take care of all of this for you. There's an 'HTML helper' that I believe you can use to format or take out the slashes on outputted text. Even then, but I could be wrong, when outputting values from a DB in CI, the slashes will automatically be stripped.
Escaping quotes and special characters is both regular practice and expected for record storage as it helps to ensure that your code can be accurately stored and extracted.
Escaping the strings for the SQL query is so that you can get the actual values into the database.
The value in the SQL query will look like O\'hara but the value that ends up in the database is O'hara.
So, you don't have to do anything at all when you display the value. Except escaping it for the environment where you display it of course. If it's displayed in a HTML document, you would HTML encode it. This will not change the apostrope ('), but it will change other characters, like < and >.
use directly
$val = real_escape_string($this->input->post('name'));
Okay, so say I have some user input that selects something from a mysql database.
I want to be safe from mysql injection so in order to do so I'd use the mysql_real_escape_string() function. But after that, I want the quote or whatever is bad from my string out of the variable completely.
EXAMPLE- :
my title variable = Herp'
escape with mysql_real_escape_string()....
then my variable = Herp\'
Now, I want the bad quote out of there. So, I want to remove the backslash & character after the backslash.. so it looks like 'Herp'.
How would I do that?
sorry if that's confusing.
If you just want to filter out quotes instead of escaping them, simply try
$myTitleVar = str_replace(array("'", '"'), '', $myTitleVar);
Before inserting it into the DB, I'd still recommend running it through mysql_real_escape_string() or even better, use PDO and parameter binding.
use stripslashes
but I would dig why that is happening. Check your magic quotes settings. For safety reasons is it good to have then set to off
I am using php5.3.6 and mysql 5.1.56 and CodeIgniter. Here is what I did.
Input some text in textarea, something like this:
what's this?
I'm bob.
$string = $_POST['name'];
$insertdata = mysql_real_escape_string($string);
Insert $insertdata into database.
It shows "what\'s this?\n\n\nI\'m bob."(without double quotes) in the table.
Query the data stored in database, use stripslashes on it and then put it back to the textarea.
It shows "what's this?nnnI'm bob."(without double quotes) in the textarea.
My questions are:
In step 4, shouldn't it be "what\'s this?\n\n\n I\'m bob." stored in the table?
I checked php manual. It says:
mysql_real_escape_string() calls
MySQL's library function
mysql_real_escape_string, which
prepends backslashes to the following
characters: \x00, \n, \r, \, ', " and
\x1a.
How am I supposed to keep the textarea input format after using mysql_real_escape_string()?
Is there anyway to choose which slash to strip and which not to?
Notes:
magic quotes option is off
I did not use stripslashes() before
using mysql_real_escape_string()
If I use addslashes() instead of
mysql_real_escape_string(),
everything works fine.
I don' want to use addslashes() since
it is not as secure as
mysql_real_escape_string(), as far as
I know.
Thanks,
Milo
This really does feel a lot like magic_quotes_gpc = On. Are you disabling it in php.ini or at runtime? It needs to be the former, otherwise it'll remain on.
http://www.php.net/manual/en/security.magicquotes.disabling.php
The magic_quotes_gpc directive may only be disabled at the system level, and not at runtime. In otherwords, use of ini_set() is not an option.
Short answer:
// double quotes are *very* important, or chars are not interpreted
$text_from_db=str_replace("\\r","\r",str_replace("\\n","\n",$text_from_db));
Long answer
Pretty simple but tricky.
You write your textarea and hit the "return" key, there is placed a \r\n (on Windows systems) with slashes that escape the "r" and "n" letter rising their special meaning of carriage return and newline.
You actually can't see them because they are "not printable" chars.
The slash char itself (0x1B) is invisible, that is a single slash is a "not printable" char, to make it visible you have to "transform" it in a printable slash char (0x5C) and to achieve that you have to double it "\\".
Now back to the question: if you can read the slash, probably that's beacuse that slash is not the 0x1B but rather 0x5C, so the "n" and "r" lose their special meaning and you get them as mere strings.
The code I posted does this conversion, converting the "[0x5C]n" string in a "[0x1B]" char.
Notes
Hope this helps, it did for me. IMPORTANT : it is not normal that the text that comes from the db has this issue if it has been stored correctly. My suggestion is to triple check insertion and retrieving because (given from the issue) you could be applying the quoting twice somewhere.
The Best Solution..
$insertdata = mysql_real_escape_string($string); (You can insert it in your database if you want)
echo stripslashes(str_replace('\r\n',PHP_EOL,$insertdata)); (The output is exactly as your input was)
You must escape data before inserting it into the database, to ensure you do not produce broken queries and to avoid SQL injections.
However, when you retrieve that data via a SELECT, you'll receive the data unescaped, ready to be used.
MySQL escapes the string, but when displaying the result back to you it will give you the same result as if it was unescaped.
I got this from for a login form tutorial:
function sanitize($securitystring) {
$securitystring = #trim($str);
if(get_magic_quotes_gpc()) {
$securitystring = stripslashes($str);
}
return mysql_real_escape_string($securitystring);
}
Could some one explain exactly what this does? I know that the 'clean' var is called up afterwards to sanitize the fields; I.e. $email = sanitize($_POST['email']);
Basically, if you have magic quotes switched on, special characters in POST/SESSION data will automatically be escaped (same as applying addslashes() to the string). The MySQL escape functions are better than PHP's addslashes() (although I can't remember the exact reasons why).
What your code does is check if the php.ini file has magic quotes turned on, if so the slashes are stripped from the data and then it is re-sanitised using the MySQL function. If magic quotes is not on, there is no need to strip slashes so the data is just sanitised with the MySQL function and returned.
First of all, this code is wrong.
It has wrong meaning and wrong name.
No SQL data preparation code does any cleaning or sanitization.
It does merely escaping. And this escaping must be unconditional.
and escaping shouldn't be mixed with anything else.
So, it must be three separated functions, not one.
Getting rid of magic quotes. Must be done separately at the data input.
trim if you wish. It's just text beautifier, no critical function it does.
mysql_real_escape_string() to prepare data for the SQL query.
So, the only mysql related function here is mysql_real_escape_string(). Though it makes no data "clean", but merely escape delimiters. Therefore, this function must be used only with data what considered as a string and enclosed in quotes. So, this is a good example:
$num=6;
$string='name';
$num=mysql_real_escape_string($num);
$string=mysql_real_escape_string($string);
$query="SELECT * FROM table WHERE name='$name' AND num='$num'";
while this example is wrong:
$num=6;
$string='name';
$num=mysql_real_escape_string($num);
$string=mysql_real_escape_string($string);
$query2="SELECT * FROM table WHERE name='$name' AND num=$num";
Even though $query2 would not throw a syntax error, this is wrong data preparation and mysql_real_escape_string would help nothing here. So, this function can be used only to escape data that treated as a string. though it can be done to any data type, there is some exceptions, such as LIMIT parameters, which cannot be treat as a strings.
trim() gets rid of all whitespace, and if magic quotes is on, the backslash is removed from any escaped quotes with stripslashes(). mysql_real_escape_string() readies a string to be used in a mysql query safely.
here are the docs for the functions used: http://php.net/manual/en/function.trim.php, http://php.net/manual/en/function.get-magic-quotes-gpc.php, http://php.net/manual/en/function.stripslashes.php, http://php.net/manual/en/function.mysql-real-escape-string.php
mysql_real_escape_string is used to escape characters in the string to add backslashes to characters such as ', which prevents an attacker from embedding additional SQL statements into the string. If the string is not escaped, additional SQL can be appended. For example, something along the lines of this might be executed:
SELECT * FROM tbl WHERE col = 'test' ; DELETE * FROM tbl ; SELECT 'owned'
magic_quotes does escaping of its own, although if I remember correctly its use is now discouraged. Besides, the MySQL function will do all the escaping you need to prevent SQL injection attacks.
Some (old) servers have magic_quotes enabled. That means that all external input is altered to (supposedly) escape it in order to be injected in a MySQL query. So O'Brian becomes O\'Brian. This was an early design decision by the PHP team that proved wrong:
You don't always need to inject input into database queries
Not all DB engines use back slashes as escape char
Escaping single quotes with backs slashes is not enough, even for MySQL
Your server security relies on a PHP setting that can be disabled
So it's way better to code without magic_quotes. The problem comes with redistributable code: you cannot know if the server will have magic_quotes enabled or disabled. So you can use get_magic_quotes_gpc() to detect it they're on and, if so, use stripslashes() to (try to) recover the original input.