secure form data for mysql - php

I have been using:
if ($_POST['Comments']!=""){
$comments = mysql_real_escape_string($_POST['Comments']);
}else{
$comments = "";
}
ever since a user added and apostraphy to their data and it broke my sql statement. I thought this also secured the data at the same time. But just now I got a submission and in the comment field in the database I see:
/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r/r
seohelp
And the email I get when someone submits had the text with the links actually working.
I thought mysql_real_escape_string() was supposed to get rid of all that?
Any suggestions? I was thinking of doing a function that does all the string cleaning for me in a few different steps. But if there is a way to secure in just one step that would be great.

mysql_real_escape_string() only protects* you against SQL Injection, not against Cross-Site Scripting (XSS).
* mysql_real_escape_string() doesn't behave properly when used in conjunction with SET NAMES because it is unaware of the charset being used. Use mysql_set_charset() instead.
In order to protect yourself against XSS, you must also use htmlentities() or htmlspecialchars() either at insert time (before mysql_real_escape_string()) or at display time.
$escaped = htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
If you want to allow some HTML content, use HTML Purifier with a whitelist of elements and attributes you want to allow.

Related

Prevent XSS and SQL injection in chat [duplicate]

Is this code secure to prevent XSS attacks ??
<?php
$string = "<b>hello world!</b>";
echo "without filtering:".$string;
echo "<br>";
$filtered = htmlspecialchars($string); // insert into database filtered
echo "After filtering:".$filtered;
echo "<br>";
$de_filtering = htmlspecialchars_decode($filtered); //retrieve from database and display
echo "After de-filtering:".$de_filtering;
?>
You should not encode HTML-Specialchars when inserting into database, that way data is manipulated (and maybe different when editing the dataset). You should rather encode them when displaying it.
But yes, htmlspecialchars() is enough to prevent XSS as long as you don't forget to use it. The way YOU use it however is as secure as before. XSS is prevented through the encoded version, the database does not care about it.
No, XSS is independent of the database. To avoid SQL-injection, you want to escape using something like mysql_real_escape_string or use prepared statements, but to avoid XSS you need to escape when outputting to HTML.
And there are a couple of gotchas there as well. Take a look at the OWASP XSS prevention cheat sheet. It explains how to escape for different context.
htmlspecialchars/htmlentities will protect you if you are outputting untrusted data between tags, but will not protect you if you are outputting it in say a javascript event handler like this:
<button onclick="confirm('do you want to delete <?php echo htmlspecialhars($untrusted_data) ?>')">
This is because you are escaping for HTML and not javascript.
Nope - you're filtering the data before putting it into the database (which is unnecessary), but cancelling out the filter when outputting the data.
Store the data in the database unfiltered, and escape it when outputting:
echo htmlspecialchars($unfiltered_data_from_database);

Why my code vulnerable to xss attack?

I have php code like this
<?php
$input_from_user = "w' onclick = 'alert(document.cookie);'";
$i_am_barcelona_fan = htmlentities($input_from_user);
?>
<input type = 'text' name = 'messi_fan' value ='<?php echo $i_am_barcelona_fan;?>' />
I am using htmlentities to protect from XSS attack, but still I am vulnerable to the above string.
Why is my code vulnerable to XSS attack? How can I protect from my code from it?
You're not telling PHP to escape quotes as well, and you should use htmlspecialchars() instead:
<input type = 'text' name = 'messi_fan' value ='<?php echo htmlspecialchars($input_from_user, ENT_QUOTES, 'UTF-8'); ?>' />
Demo
Never ever (ever) trust foreign input introduced to your PHP code. Always sanitize and validate foreign input before using it in code. The filter_var and filter_input functions can sanitize text and validate text formats (e.g. email addresses).
Foreign input can be anything: $_GET and $_POST form input data, some values in the $_SERVER superglobal, and the HTTP request body via fopen('php://input', 'r'). Remember, foreign input is not limited to form data submitted by the user. Uploaded and downloaded files, session values, cookie data, and data from third-party web services are foreign input, too.
While foreign data can be stored, combined, and accessed later, it is still foreign input. Every time you process, output, concatenate, or include data in your code, ask yourself if the data is filtered properly and can it be trusted.
Data may be filtered differently based on its purpose. For example, when unfiltered foreign input is passed into HTML page output, it can execute HTML and JavaScript on your site! This is known as Cross-Site Scripting (XSS) and can be a very dangerous attack. One way to avoid XSS is to sanitize all user-generated data before outputting it to your page by removing HTML tags with the strip_tags function or escaping characters with special meaning into their respective HTML entities with the htmlentities or htmlspecialchars functions.
Another example is passing options to be executed on the command line. This can be extremely dangerous (and is usually a bad idea), but you can use the built-in escapeshellarg function to sanitize the executed command’s arguments.
One last example is accepting foreign input to determine a file to load from the filesystem. This can be exploited by changing the filename to a file path. You need to remove ”/”, “../”, null bytes, or other characters from the file path so it can’t load hidden, non-public, or sensitive files.
Learn about data filtering (http://www.php.net/manual/en/book.filter.php)
Learn about filter_var (http://php.net/manual/en/function.filter-var.php)

Prevent XSS attacks

Is this code secure to prevent XSS attacks ??
<?php
$string = "<b>hello world!</b>";
echo "without filtering:".$string;
echo "<br>";
$filtered = htmlspecialchars($string); // insert into database filtered
echo "After filtering:".$filtered;
echo "<br>";
$de_filtering = htmlspecialchars_decode($filtered); //retrieve from database and display
echo "After de-filtering:".$de_filtering;
?>
You should not encode HTML-Specialchars when inserting into database, that way data is manipulated (and maybe different when editing the dataset). You should rather encode them when displaying it.
But yes, htmlspecialchars() is enough to prevent XSS as long as you don't forget to use it. The way YOU use it however is as secure as before. XSS is prevented through the encoded version, the database does not care about it.
No, XSS is independent of the database. To avoid SQL-injection, you want to escape using something like mysql_real_escape_string or use prepared statements, but to avoid XSS you need to escape when outputting to HTML.
And there are a couple of gotchas there as well. Take a look at the OWASP XSS prevention cheat sheet. It explains how to escape for different context.
htmlspecialchars/htmlentities will protect you if you are outputting untrusted data between tags, but will not protect you if you are outputting it in say a javascript event handler like this:
<button onclick="confirm('do you want to delete <?php echo htmlspecialhars($untrusted_data) ?>')">
This is because you are escaping for HTML and not javascript.
Nope - you're filtering the data before putting it into the database (which is unnecessary), but cancelling out the filter when outputting the data.
Store the data in the database unfiltered, and escape it when outputting:
echo htmlspecialchars($unfiltered_data_from_database);

Best ways to sanitize user submitted content? [duplicate]

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.

Specifying some part of the page to be interpreted as plain text

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.

Categories