Prevent XSS attacks - php

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);

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);

Protecting my html forms from injection

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.

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.

secure form data for mysql

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.

Categories