Suppose I am importing a passage by file_get_contents() or getting user input, there may be single quotes or double quotes or both. What is the safe way to cast the said content into a variable and do manipulation afterward?
It depends on what you are about to do with the input later on:
Output as HTML:
$input = htmlspecialchars($input);
Use it in a shell command:
$input = escapeshellarg($input);
Use it in a database query
If you use prepared statements you are fine. If not (why?), use:
$input = mysqli_real_escape_string($mysqli, $string);
// or
$input = PDO::quote($input);
// other database extension may introduce their own quoting functions
Use it in a regular expression:
$input = preg_quote($input);
Extension or correction of this list is appreciated.... :)
Related
So let's say we have a following code:
<?php
$str = addslashes($_GET['str']);
$cmd = 'sometool "'.$str.'"';
system($cmd);
?>
Is it secure? Can I escape from double quotes somehow? The operating system in linux.
Purely theoretical consideration. I don't use it in my code ;)
It's not secure. You can still pass some arguments that will be malicious, i.e. execute other files in system.
$var = '$(sh file.sh)';
$str = addslashes($var);
$cmd = 'sometool "'.$str.'"';
system($cmd);
You should use escapeshellarg method for escaping shell arguments.
$str = escapeshellarg($_GET['str']);
$cmd = 'sometool ' . $str;
system($cmd);
Note that you have to use the argument $str as it is and that it will be a single argument. You must not surround it with quotes ' or double quotes "
Definitively not secure as is,
Like any user's input, you'll have to not only escape quotes, but also verify the conformity of the data being submitted and have to be strict on that.
For e.g.: if the "sometool" command is waiting for a path, you've to ensure that the user input is a valid path. If the path has to be in a restricted location, you've to check that restriction.
Assuming that your "str" has to be a valid string, you can begin with the filter input function.
https://www.php.net/manual/en/function.filter-input.php
Make sure to use the appropriate filters (for quotes, encoding, etc.) : https://www.php.net/manual/en/filter.filters.php.
It will not be possible to by-pass the escaping here.
This somehow ensure the conformity of the data, but still, you've to be sure that the command "sometool" itself will not be affected by any valid string characters or syntax, that's what makes it still unsecure to use.
Suppose you have the following:
<?php
$connection = mysqli_connect("host", "root", "passwd", "dbname");
$habits = mysqli_real_escape_string($connection, $_POST['habits']);
?>
Lets say you entered, for a field called 'habits', the value 'tug o' war'. Therefore, the mysqli_real_escape_string function will escape the second quote symbol and the database engine won't be fooled into thinking that the value is 'tug o'. Instead, it will know that the value is actually 'tug o' war'. My question is, why then do you need a stripslashes function? A stripslashes function will simply strip away the good work that was done by the mysqli_real_escape_string function. Stripping away a backslash will simply return you to where you were, and the database will be fooled again. Am I to assume that the stripslashes function is NOT used for database purposes? That is, would this piece of code be completely nonsensical?:
<?php
$connection = mysqli_connect("host", "root", "passwd", "dbname");
$habits = mysqli_real_escape_string($connection, $_POST['habits']);
$undosomething = stripslashes($habits);
echo '$undosomething';
?>
If stripslashes is NOT used for database purposes, what exactly is it used for?
(As of 2014) It still has it's uses. It's not really used with a database but even with this, there are use cases. Let's assume, or send data from form using JavaScript and you have a string with a quote such as "It's". Than getting the value through the $_GET supervariable, you'll get the value "It's". If you than use mysqli_real_escape_string() or similar (which you must use for security), the quote will be double encoded and the backslash will be saved to the DB. For such scenarios, you would use this function. But it is not for security and not necessarily used with a DB.
Per the Manual, the purpose of stripslashes() is to unquote a quoted string, meaning to remove a backslash quoting a character. Note, PHP lacks a character data type, so all single characters are strings. You may wish to peruse this example code which demonstrates that this function leaves forward slashes as well as escape sequences involving non-printable characters unaltered. Stripslashes() arose to counter excessive quoting caused by a feature that PHP formerly supported: magic quotes.
In the early days of PHP when Rasmus Lerdorf worked with databases that necessitated escaping the single quote character, he found a way to avoid the tedium of manually adding a backslash to quote or escape that character; he created magic quotes:
... useful when mSQL or Postgres95 support is enabled
since ... single quote has to be escaped when it is
part of [a] ... query ...
(See php.h in PHP/FI [php-2.0.1] )
While magic quotes saved developers from having to use addslashes(), this feature could automatically quote inappropriately. A form's input with a value of O'Reilly would display as O\'Reilly. Applying stripslashes() fixed that issue. Though stripslashes() lived up to its name and stripped away backslashes, it was inadequate for addressing all the problems associated with magic quotes, a feature that would ultimately be deprecated in PHP5.3 and then removed as of PHP5.4 (see Manual).
You may view quoted data if you are still using a version of PHP that supports magic quotes. For example, consider the case of a $_GET variable that originates from a JavaScript containing a url-encoded string, as follows:
location.href="next_page.php?name=O%27Riley"; // $_GET['name'] == O\'Riley
If you were to apply to $_GET['name'] either addslashes() or mysqli_real_escape_string(), this variable's value would expand, containing two more backslashes, as follows:
O\\\'Riley
Suppose the variable were next used in an insert query. Normally the backslash of a quoted character does not get stored in the database. But, in this case, the query would cause data to be stored as:
O\'Riley
The need for stripslashes() is much less likely nowadays, but it's good to still retain it. Consider the following JavaScript, containing a flagrant typo:
location.href="http://localhost/exp/mydog.php
?content=My%20dog%20doesn\\\\\\\\\\\\\%27t%20
like%20to%20stay%20indoors."
Using stripslashes(), one may dynamically correct the code as follows:
function removeslashes($string)
{
while( strpos( $string, "\\" ) !== FALSE ) {
$string = stripslashes( $string );
}
return $string;
}
$text = htmlentities($_GET['content']);
if (strpos($text,"\\") !== FALSE ) {
echo removeslashes( $text );
}
Note: stripslashes() is not recursive.
There is no point to stripslashes().
Some folks used to think this provided them security, but as you can see it does not. It should be removed from PHP completely, but it hasn't been.
addslashes():
w3schools.com - function returns a string with backslashes in front of predefined characters.
php.net - Quote string with slashes
stripslashes():
w3schools.com - function removes backslashes added by the addslashes() function.
php.net - Un-quotes a quoted string
<?php
$str = "Who's Peter Griffin?";
echo $str . " This is original string." . PHP_EOL;
echo addslashes($str) . " This is addslashes string." . PHP_EOL;
echo stripslashes(addslashes($str)) . " This is stripslashes string." . PHP_EOL;
?>
Embed PHP online:
body, html, iframe {
width: 100% ;
height: 100% ;
overflow: hidden ;
}
<iframe src="https://ideone.com/2DNzNJ"></iframe>
Neither mysqli_real_escape_string nor stripslashes protect against SQL injection.
Use prepared statements.
Example Code.
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "my_database");
/* Prepared statement, stage 1: prepare */
$stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?)");
$id = 1;
$stmt->bind_param("i", $id);
$stmt->execute();
I'm trying to compare the contents of elements using xpath.
Sample code:
div[# class = "name" and. = "'.$ data.'"]
Unfortunately, sometimes $data contains "es or other special characters.
example:
My school is a "super"
In this case, I can not compare content. What can I do with this?
The other answers (up to know) all suffer from escaping too many characters (eg., addslashes($string) also escapes double quotes).
Anyway, PHP only supports XPath 1.0 which suffers from bad escaping capabilities. From XPath 2.0 on, one can escape the quotes used to declare the string by doubling them (eg., 'foo''bar' will return foo'bar). In XPath 1.0, there is no way to do so.
One way to get out of this would be to ignore single quotes in both the input and search value by using
$string = str_replace("'", "", $data);
$xpath = "div[#class = 'name' and translate(., \"'\", '') = '$string']";
The str_replace line removes all single quotes from the search token, and the translate call within XPath removes all single quotes from the string to compared with.
You can use htmlentities or html_entity_decode, the way it suits you better, I didn't understood if you have special characters, or they were in the data.
Check php documentation.
PHP has a function called "addSlashes" to fix this problem. It's use:
addSlashes(your_php_variable);
A function called addslashes() escapes special characters such as quotes.
Try this:
div[# class = "name" and. = "'.<?php echo addslashes($data) ?>.'"]
to sanitize user input we usually use mysql_real_escape_string, but for example if i want to escape: O'Brian it will return O\'Brian and I don't really like this because if i want to print this name, I have to strip slasheseverytime.
So I thought to use this function:
$search = array("'", '"');
$replace = array("´", "“");
$str_clean = str_replace($search, $replace, "O'Brian");
Is this simple function protecting me from MySQL-Injection?
Thank very much and sorry for my bad English.
No - no more escaping!
Use mysqli or PDO and prepared statements
http://php.net/manual/en/mysqli.prepare.php
http://php.net/manual/en/pdo.prepared-statements.php
mysql_real_escape_string does add the \ for string escaping only and does not add them to the database, so you don't have to use stripslashes while displaying the content.
If you are really getting the \ stored in the database, do off the magic_quote
You should always use mysql_real_escape_string to escape input. This is for when you're writing values into your database, not when you're reading values from your database. When you write "O\'Brian" to your database, it's stored as "O'Brian", and when you read it back out, you should also get "O'Brian" (and won't need to strip the slashes, since they don't exist).
Yes, obviously it's protecting from SQL Injection attacks
It Escapes special characters in the unescaped_string, taking into account the current character set of the connection so that it is safe to place it in a mysql_query().
I have built a search engine using php and mysql.
Problem:
When I submit a word with an apostrophe in it and return the value to the text field using $_GET the apostrophe has been replaced with a backslash and all characters after the apostrophe are missing.
Example:
Submitted Words: Just can't get enough
Returned Value (Using $_GET): Just can\
Also the url comes up like this:search=just+can%27t+get+enough
As you can see the ' has been replaced with a \ and get enough is missing.
Question:
Does anybody know what causes this to happen and what is the solution to fix this problem?
The code:
http://tinypaste.com/11d62
If you're running PHP version less than 5.3.0, the slash might be added by the Magic Quotes which you can turn off in the .ini file.
From your description of "value to the text field" I speculate you have some output code like this:
Redisplay
<input value='<?=$_GET['search']?>'>
In that case the contained single quote will terminate the html attribute. And anything behind the single quote is simply garbage to the browser. In this case applying htmlspecialchars to the output helps.
(The backslash is likely due to magic_quotes or mysql_*_escape before outputting the text. I doubt the question describes a database error here.)
Update: It seems it's indeed an output problem here:
echo "<a href='searchmusic.php?search=$search&s=$next'>Next</a>";
Regardless of if you use single or double quotes you would need:
echo "<a href='searchmusic.php?search="
. htmlspecialchars(stripslashes($search))
. "&s=$next'>Next</a>";
(Notice that using stripslashes is a workaround here. You should preserve the original search text, or disable the magic_quotes rather.)
Okay I forgot something crucial. htmlspecialchars needs the ENT_QUOTES parameter - always, and in your case particularly:
// prepare for later output:
$search = $_GET['search'];
$html_search = htmlspecialchars(stripslashes($search), ENT_QUOTES);
And then use that whereever you wanted to display $search before:
echo "<a href='searchmusic.php?search=$html_search&s=$next'>Next</a>";
Single quotes are important in PHP and MySQL.
A single quote is a delimeter for a string in PHP, for example:
$str = 'my string';
If you want to include a literal quote inside a string you must tell PHP that the quote is not the end of the string. It is escaped with the backslash, for example:
$str = 'my string with a quote \' inside it';
See PHP Strings for more on this.
MySQL operates in a similar way. An example query might be:
$username = 'andyb';
$quert = "SELECT * FROM users WHERE user_name = '$username'";
The single quote delimits the string parameter. If the $username included a single quote, this would cause the query to end prematurely. Correctly escaping parameters is an important concept to be familiar with as it is one attack vector for breaking into a database - see SQL Injection for more information.
One way to handle this escaping is with mysql_real_escape_string().