I normally use this function to sanitize my form inputs before storing them into my database:
//Function to sanitize values received from the form. Prevents SQL injection
function clean($str) {
$str = #trim($str);
if(get_magic_quotes_gpc()) {
$str = stripslashes($str);
}
return mysql_real_escape_string($str);
}
Until today I didn't realize that mysql_real_escape_string required a database connection as I've only used it when I've been cleaning the data before storing it into the database.
I tried using the function on a contact form and got the "A link to the server could not be established" error. I could connect to the database but there is no need because I simply am trying to sanitize the data before it's being sent out to my e-mail via the contact form.
What is the best way to sanitize data that's not being stored in a mysql database and does this data still need to be sanitized?
use filter_var()
http://php.net/manual/en/function.filter-var.php
like if you want to sanitize an email:
$_POST['email'] = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
to message
$_POST['message'] = filter_var($_POST['message'], FILTER_SANITIZE_STRING);
is enogth
The purpose of sanitizing the data with mysql_real_escape_string is to avoid SQL injection. If you're not using SQL, you're already immune.
Men don't get cervical cancer.
Use a sanitization function appropriate to the special characters you need to avoid. Ideally, don't strip something which won't cause harm.
The whole concept is wrong.
This function doesn't help not for email not even for database.
mysql_real_escape_string do not "sanitize" anything. It is merely escape delimiters and nothing else. Just to prevent syntax errors if you have a delimiter in your data:
SELECT * FROM table WHERE name = 'it's me' # error!
after data being escaped, your data become 'it\'s me' and there is no error.
Therefore, this function works only with SQL query and for data, enclosed in quotes only.
Thus, there is no sense in doing just mysql_real_escape_string without having quotes around. mysql_real_escape_string should be used
a) alone. stuff like trim or stripslashes has nothing to do here
b) right before query string composing and not elsewhere
c) only with data that going to be enclosed in quotes.
d) all other data need another ways of sanitization
As for the email, you don't need any sanitization it you send it as plain text.
The only precaution you have to take is against mail injection
Not a big deal though. Just put user input into message body only. not into subject, to or from or any other header. Message body only. And you are safe
(I'm new to stackoverflow so I'm going about this the wrong way/doing a bad job with the styling of my answer feel free to let me know.)
Correct me if I'm wrong as I'm also dealing with the same issue right now, but I don't think that the accepted answer using filter_var is enough as attackers could bypass this using unicode.
Example: "& #66;& #99;& #99;& #58;" (spaces added so stackoverflow will display it correctly)
This wouldn't get removed from the string, and would later be replaced with "Bcc:".
This is my solution, but there may be a better way. If anyone knows of one I'd love to hear it.
$string = str_replace("&", "(and)", $string);
$string = str_replace("#", "(num)", $string);
$string = str_replace(";", "(semi-colon)", $string);
$string = str_replace(":", "(colon)", $string);
$string = str_replace("#", "(at)", $string);
$string = str_replace("\\", "(backslash)", $string);
$string = filter_var($string, FILTER_SANITIZE_STRING);
Related
I have found from different blogs that it is strongly recommended to use htmlspecialchars() to output any data on screen to be safe from XSS Attack.
I am using filter_input() to filter any data that comes from user before inserting into database. filter_input() convert special characters like ' to ' and saved it that way,like
I'm going to shopping with Molly's sister;Dolly
.My question is
How can I print(output) apostrope or quotes and specific special characters to users screen using htmlspecialchars so that the output would be user friendly
I have tried to use htmlspecialchars($post,ENT_NOQUOTES);,but it gives me same copy of data that is stored in database.If I don't use htmlspecialchars(),just $post gives me expected result,which I think is vulnerable to XSS Attack
Thanks for your time,and look forward to get help from peers.
EDIT
I got suggestions to use htmlspecialchars_decode() or html_entity_decode() on answer,but
(https://stackoverflow.com/users/1338292/ja͢ck)
and some other suggested not to use these functions to output data on screen.
Please be informed that I am using prepared statement and parameterized query.But I don't want to keep any security holes,that's why filtering data before sending into database.
As I have used filter_input() to filter data before sending to database,is it safe to output data directly($post=$posted_data;) from database without using htmlspecialchars?
If I must need to use htmlspecialchars to output data,then how can I do it in this case?
Code Sample
$stmt1=mysqli_stmt_init($connect_dude);
/*Inserting into database*/
if(isset($_POST['titlex']) && isset($_POST['pricex']) && isset($_POST['detailx'])){
$tit=filter_input(INPUT_POST,'titlex',FILTER_SANITIZE_STRING);
$pri=preg_replace('#[^0-9]#','',$_POST['pricex']);
$det=filter_input(INPUT_POST,'detailx',FILTER_SANITIZE_STRING);
$query2="INSERT INTO `hotel1`.`dine` (user_id,title,price,detail) VALUES (?,?,?,?)";
mysqli_stmt_prepare($stmt1,$query2);
mysqli_stmt_bind_param($stmt1, "isis", $logged_id, $tit, $pri, $det);
mysqli_stmt_execute($stmt1);
}
/*Get Data from DB*/
$query1="SELECT id101,title,price,detail FROM `hotel1`.`dine` WHERE user_id=?";
mysqli_stmt_prepare($stmt1,$query1);
mysqli_stmt_bind_param($stmt1, "i", $user_idx);
mysqli_stmt_execute($stmt1);
mysqli_stmt_store_result($stmt1);
mysqli_stmt_bind_result($stmt1, $id101, $title,$price, $detail);
while(mysqli_stmt_fetch($stmt1)){
$id101=$id101;
$title=$title; //htmlspecialchars needed
$price=$price; //htmlspecialchars needed
$detail=$detail; //htmlspecialchars needed
........................
........................
}
I am using filter_input() to filter any data that comes from user before inserting into database.
This is a bad practice. Do not mangle your data before you insert it into a database. It's 2015; don't sanitize, use prepared statements instead.
$db = new \PDO(
'mysql:host=localhost;dbname=mydatabase;charset=UTF-8',
$username,
$password
);
// other stuff in between
$statement = $db->prepare(
"INSERT INTO yourtable (email, username) VALUES (:email, :username);"
);
$success = $statement->execute([
':email' => $_POST['email'],
':username' => $_POST['username']
]);
Prepared statements remove the need for filter_input(). You're not adding defense in depth by doing this, you're just ruining data integrity and giving yourself a headache.
When you render your output, if you want to allow HTML, use HTML Purifier.
Otherwise, use htmlspecialchars($output, ENT_QUOTES | ENT_HTML5, 'UTF-8') for best results.
Recommended Reading: Web Application Security by Taylor Hornby.
I think there's a problem with your strategy.
You certainly need to filter input and output stuff but you're overlaying them - double escape.
The problem is your input filter is doing also the output filter's work.
As I have used filter_input() to filter data before sending to database,is it safe to output data directly($post=$posted_data;) from database without using htmlspecialchars?
No. Don't trust your database, or at least not always. It wouldn't be the first case an SQL injection caused a huge XSS.
If I must need to use htmlspecialchars to output data,then how can I do it in this case?
As I said above, stop using input filter for output filtering. Your input filter should just make sure the data is safe for internal use - to protect your application against not-indented operations. Thus you don't need to escape HTML before inserting to database, and as a bonus you'll save space.
On the other hand output filter cares about the end-user. You take the data from db and send it to the user. We're talking about htmlspecialchars which is fine with ENT_QUOTES but in my opinion is not sufficient. You should also escape characters like ( ) [ ] = + - \ since there are cases you don't need for a successful XSS attack to open/end any tag or use quotes. For example when you output data into onclick, etc.
I just saw that htmlspecialchars has double_encode parameter, which would eventually solve your problem:
htmlspecialchars($string, ENT_QUOTES, "UTF-8", false);
Doing this will always keep HTML special chars escaped and won't escape already escaped stuff.
You want to go the other way around :) htmlspecialchars_decode()
You dont need to, when you encode them and save them to DB, they will be shown on the web page (when you use echo $result['message'];) as they should. Browsers automaticaly decode them.
I am using this function to strip input:
function stripinput($text) {
if (!is_array($text)) {
$text = trim($text);
$text = preg_replace("/(&)+(?=\#([0-9]{2,3});)/i", "&", $text);
$search = array("&", "\"", "'", "\\", '\"', "\'", "<", ">", " ");
$replace = array("&", """, "'", "\", """, "'", "<", ">", " ");
$text = str_replace($search, $replace, $text);
}else{
foreach ($text as $key => $value) {
$text[$key] = stripinput($value);
}
}
return $text;
}
I have a text box on my site that allows the use of html formatting to allow the users to make the text more presentable.
I use this code to protect most inputs to my db.
function clean($str) {
$str = #trim($str);
if(get_magic_quotes_gpc()) {
$str = stripslashes($str);
}
return mysql_real_escape_string($str);
}
What i don't want it to do is remove html elements like <p> and <strong>
is there a better way to protect the inputs in text areas?
I only use mysql_real_escape_string() when inserting data to my DB and remove Tags like <script> (and some others) after pulling it from the DB. I think there are a few regexes out there.
The first line of defense against injections is using prepared statements. If you use prepared statements for your queries then it really doesn't matter what the user puts into your form because you have already separated code from data. The database will see any code that a user injects as just data rather than code. So not only do you get the benefit of protecting yourself from injection, but your code is actually cleaner and more thought out as well.
Should I disallow characters like ",',>,<,\ ... to be typed in an upload forms text field? The text will be send through PHP to a blog.
I heared that some characters might cause trouble and could be used to "hack / harm" servers. Which characters should be restricted?
Thanks for your input.
Michael
There is no need to restrict anything. The problem is that you have to sanitize all user input; for this specific type of data (possible HTML) it is necessary and enough to use htmlspecialchars on all user-provided data before displaying it as part of your page.
For example, if your form has a textarea named post-body, you should receive the user input (e.g. with $_REQUEST['post-body']) and save it to your database as-is (warning: use mysql_real_escape_string or PDO to protect yourself from SQL injection at this stage!). When the time comes to display it, you would retrieve it from the database and print it with something like
echo htmlspecialchars($postBody);
See this question for some more background on data sanitization.
Users data should be sanitized by htmlspecialchars function each time when you output users data, to avoid XSS-attacks.
Also, to work with users data in sql-queries, use PDO and prepared statements or mysql_real_escape_string function to avoid SQL-injection. Example.
<? $string = str_replace("\\\"", "\"", $string);
$string = htmlspecialchars($string);
$string = preg_replace( "/\r\n|\n|\r/", "<br>", $string ); ?>
<input type = "text" name = "string" id = "string" value = "<?=$string?>">
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
PHP: the ultimate clean/secure function
I am working on an experimental social networking site in PHP. So, there will be a lot of user submitted data sent to the database.
I had coded a custom block script a while back, that would just block certain characters or keywords from being submitted. This worked, but it had it's list of problems.
I heard addslashes and mysql_real_escape_string will do this, but I don't want to do anything until I get some solid advice.
I tried addslashes, and it will add slashes to can't, don't, etc. I don't want that.
I just want my database to be safe from xss, html, php, and javascript attacks. Any advice?
prepared statements from PDO
filter_var() functions
htmlspecialchars()
For people who don't know PHP or find documentation about functions:
prepared statements - will provide protection against SQL injections ( but not against extreme stupidity )
filter_var() - will let you make sure that data really us an URL or email address , etc.
htmlspecialchars() - converts characters like < , > and & into html entities, thus, protecting against XSS.
I really fail to see the need for explanation here.
You should HTML escape any content before outputting it back to the user. Then when it's ever outputted back it'll be safe. Use htmlspecialchars for PHP. See What are the best practices for avoiding xss attacks in a PHP site for more information and read OWASP XSS (Cross Site Scripting) Prevention Cheat Sheet.
All good answers so far, I would just like to add that you should make sure that the input data comes in the desired encoding - you should also normalize the different types of new line feeds or strip control characters altogether, I end up using the following function a lot:
function Filter($string, $control = true)
{
$string = iconv('UTF-8', 'UTF-8//IGNORE', $string);
if ($control === true)
{
return preg_replace('~\p{C}+~u', '', $string);
}
return preg_replace(array('~\r[\n]?~', '~[^\P{C}\t\n]+~u'), array("\n", ''), $string);
}
It will remove all invalid UTF-8 data from the string and normalize new lines. All control chars (except tab (\t) and new lines (\n)) are striped, and if $control == true these are stripped too.
PS: This is not very useful from a security standpoint of view but is helps avoiding GIGO.
For HTML type input use HTMLPurifier or similar to filter out unwanted markup.
Validate form fields before storing the data
Use prepared statements with PDO or MySQLi when writing to the database. This will take care of the SQL escaping for you, provided you bind your parameters correctly.
Escape the output coming out of the DB before displaying it unless it can be considered safe.
I am beginner in web development, I am developing a site that allows user to post various discussions and others comment and reply on it. The problem I am facing is, the user can post almost anything, including code snippets and any other thing which might possible include single quotes, double quotes and even some html content.
When such posts are being posted, it is intervening with the MySQL insert query as the quotes are ending the string and as a result the query is failing. And even when I display the string using php, the string is being interpreted as html by the browser, where as I want it to be interpreted as text. Do I have to parse the input string manually and escape all the special characters? or is there another way?
You need to read up on a few things
SQL Injection - What is SQL Injection and how to prevent it
PHP PDO - Using PHP PDO reduces the risk of injections
htmlentities
The basic premise is this, sanitize all input that is coming in and encode everything that is going out. Don't trust any user input.
If possible, whitelist instead of blacklisting.
EDIT :
I you want to display HTML or other code content in there, users need to mark those areas with the <pre> tag. Or you could use something like a markdown variation for formatting.
Use PDO, prepared statements and bound parameters to insert / update data, eg
$db = new PDO('mysql:host=hostname;dbname=dbname', 'user', 'pass');
$stmt = $db->prepare('INSERT INTO table (col1, col2) VALUES (?, ?)');
$stmt->execute(array('val1', 'val2'));
Edit: Please note, this is a very simplified example
When displaying data, filter it through htmlspecialchars(), eg
<?php echo htmlspecialchars($row['something'], ENT_COMPAT, 'UTF-8') ?>
Update
As noted on your comment to another answer, if you want to maintain indentation and white-space when displaying information in HTML, wrap the content in <pre> tags, eg
<pre><?php echo htmlspecialchars($data, ENT_COMPAT, 'UTF-8') ?></pre>
Look at mysql_real_escape_string and htmlentities functions in PHP manual.
You can also read the Security chapter in PHP manual.
To avoid the breaking of queries in database (which means you're not escaping them, leaving big holes for sql injection) you use mysql_real_escape_string($string) on the value before passing it to the query string, enclosing it in quotes also.
Ex. $value = mysql_real_escape_string($value); // be sure to have an open connection before using this function.
$query = "select * from `table` where value = '".$value."'";
As for displaying in html, you should at least echo htmlentities($string) before outputting it to the browser.
Like echo htmlentities($mystring, ENT_QUOTES)`;
Edit:
To preserve withe spaces, you can use nl2br function (which converts linebrakes to the html equivalen <br />) or go for a little deeper $string = nl2br(str_replace(" ", " ", $string));, but html code would look a bit ugly, at least for me
Reference: htmlentities and mysql_real_escape_string. nl2br
use mysql_real_escape_string. It is a good practice to use this on all user inputs to prevent SQL Injection attacks.