I'm not sure , how I can really make a safe inputs with strings.
For example I got:
$id = intval($_POST['id']);
$name = $_POST['name'];
$sql->query("UPDATE customers SET name = " . $sql->escape_string($name) . " WHERE id = {$id}");
I'm sure that $name isn't secured enough. How can I secure it, to prevent from XSS vulnerability?
Kind Regards,
cyclone.
XSS protection should be done on the output side, not your storage medium (the database). The database does not know where the data is displayed at. If the data to be stored is text (as in this case with $name), you should store it as text and not HTML.
If you really want to get rid of possible HTML tags, use $name = strip_tags($_POST['name']), but the correct way to prevent XSS vulns is escaping it on the output side with htmlspecialchars (or htmlentities).
If you want to use the PHP filter functions, here is an example that removes HTML tags:
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
PHP Docs:
filter_input function
Sanitize filters
XSS has nothing to do with your database, well mostly.
Cross-site scripting (XSS) is a type of computer security
vulnerability typically found in Web applications that enables
attackers to inject client-side script into Web pages viewed by other
users.
Maybe your referring to SQL injection? You've escaped input already, you can further sanitize it by casting variables to appropriate types.
When it comes to security, I always think it makes sense to be as strict as possible, but no stricter. If you can determine that a name is invalid before inserting it into the database, why not reject it then?
Does anyone have a name with an HTML tag in it? Probably not. But how about an apostrophe or hyphen? Definitely.
With that in mind, let's see what a valid name would look like:
Letters
Spaces
Apostrophes
Hyphens
Periods (for initials)
Now that you've determined what a valid name looks like, reject all names that do not meet this criteria:
/* If the input contains any character that is not a capital letter,
a lowercase letter, whitespace, a hyphen, a period, or an apostrophe,
then preg_match with return true. */
if (preg_match('/[^A-Za-z\s\-\.\']/', $_POST['Name']))
{
// Invalid name
}
else
{
// Valid name
}
The code you've provided is aimed at protecting again SQL Injection attacks, not XSS attacks, which are a completely different thing.
SQL Injection is where the attacker uses SQL code to get data in or out of your database in a way that you did not intend. Properly escaping the SQL string as you're doing will mitigate against this. (that said, I don't know from your code what class the $sql object is, and thus I can't tell you whether $sql->escape_string() is a sufficient protection; I assume it is, but would need to know more about the object to be sure)
XSS ("Cross-site scripting") attacks are where an attacker managed to get his HTML, CSS or Javascript code into your page, resulting in subsequent page loads being displayed with unwanted content.
This can be achieved by the attacker in a variety of ways, but typically you should ensure that any data input by users which will be displayed on your site should be filtered to prevent it containing HTML, CSS or JS code. If it does, you should either strip the code out entirely or use HTML escaping (PHP's htmlentities() function and similar) to ensure that it is displayed in a safe manner.
You are currently not doing anything to prevent this at all in the code you've shown us, but equally from the code you've shown us, we can't tell whether this data needs to be protected against XSS attacks. This would depending on when and how it is used.
For cleaning entries before putting them in sql, I always do this:
trim($string) // Cuts off spacing and newlines in the beginning or end
And
mysql_real_escape_string($string) // prevents SQL injections
Note: Any part of the sql query string can be mysql_real_escape_string'd. The entire string does not have to be; as long as some part of escaped, the query will be safe from injection.
Related
Is converting special characters to HTML entities in form validation and database query using PHP PDO using htmlspecialchars() function really necessary?
For example, I have a website with simple login system more or less like:
$username = (string) htmlspecialchars($_POST['user']);
$password = (string) htmlspecialchars($_POST['pass']);
$query = $dbh->prepare("select id where username = ? and password = ?")
$query->execute($username, $password);
Note that I also use type casting besides the function in question.. So, is it necessary? Or I can safely use $username = $_POST['user']; ?
Your confusion is quite common because information and examples in books and on the internet including php.net are misleading or ambiguous. The most important thing you can learn when developing web apps is filter input, escape output.
Filter Input
This means that for any data input whether provided by a user on a form or provided by a file from some other source, filter out anything which does not belong. An example would be that if you expect a numeric value, filter out any non-numeric characters. Another example would be limit/ensure the maximum length of data. However, you don't need to get to crazy with this. For example, if you expect a line of text that can contain literally any combination of characters, then trying to come up with a filter will probably only frustrate your users.
So, you generally would store input data in your database as provided with optionally some filtering before hand.
Escape Output
What is meant by escape output is to properly make safe the data for a given media. Most of the time, this media is a web page (html). But, it can also be plain text, xml, pdf, image, etc. For html, this means using htmlspecialchars() or htmlentities() (you can read up on the differences here). For other media types, you would escape/convert as appropriate (or not at all if appropriate).
Now, your question is whether or not you should use htmlspecialchars() on input data that will be used as sql query parameters. The answer is no. You should not modify the data in any way.
Yes, the data contained in $_POST should be considered dangerous. Which is why you should 1) guard against sql injection using prepared statements and bound parameters as you are doing and 2) properly escape/convert data found in $_POST if you place it in html.
There are many frameworks for PHP which handle these details for you and I recommend you pick and use one. However, if you do not, you can still build a safe and secure application. Whether you use a framework or not, I strongly suggest that you read the recommendations suggested by OWASP. Failure to do so will only result in a security nightmare for your web application.
You should use htmlspecialchars when you have some plain text (such as user input, or user input that you previously stored in a database and just took out of it with a SELECT, or text fetched via HTTP from a third party, etc, etc) and you want to insert it into an HTML document. This protects you against XSS.
In general, you should not use it when inserting data into a database (a database is not an HTML document). You might want to use it in some non-HTML form later.
Is converting special characters to HTML entities in form validation and database query using PHP PDO using htmlspecialchars() function really necessary?
For example, I have a website with simple login system more or less like:
$username = (string) htmlspecialchars($_POST['user']);
$password = (string) htmlspecialchars($_POST['pass']);
$query = $dbh->prepare("select id where username = ? and password = ?")
$query->execute($username, $password);
Note that I also use type casting besides the function in question.. So, is it necessary? Or I can safely use $username = $_POST['user']; ?
Your confusion is quite common because information and examples in books and on the internet including php.net are misleading or ambiguous. The most important thing you can learn when developing web apps is filter input, escape output.
Filter Input
This means that for any data input whether provided by a user on a form or provided by a file from some other source, filter out anything which does not belong. An example would be that if you expect a numeric value, filter out any non-numeric characters. Another example would be limit/ensure the maximum length of data. However, you don't need to get to crazy with this. For example, if you expect a line of text that can contain literally any combination of characters, then trying to come up with a filter will probably only frustrate your users.
So, you generally would store input data in your database as provided with optionally some filtering before hand.
Escape Output
What is meant by escape output is to properly make safe the data for a given media. Most of the time, this media is a web page (html). But, it can also be plain text, xml, pdf, image, etc. For html, this means using htmlspecialchars() or htmlentities() (you can read up on the differences here). For other media types, you would escape/convert as appropriate (or not at all if appropriate).
Now, your question is whether or not you should use htmlspecialchars() on input data that will be used as sql query parameters. The answer is no. You should not modify the data in any way.
Yes, the data contained in $_POST should be considered dangerous. Which is why you should 1) guard against sql injection using prepared statements and bound parameters as you are doing and 2) properly escape/convert data found in $_POST if you place it in html.
There are many frameworks for PHP which handle these details for you and I recommend you pick and use one. However, if you do not, you can still build a safe and secure application. Whether you use a framework or not, I strongly suggest that you read the recommendations suggested by OWASP. Failure to do so will only result in a security nightmare for your web application.
You should use htmlspecialchars when you have some plain text (such as user input, or user input that you previously stored in a database and just took out of it with a SELECT, or text fetched via HTTP from a third party, etc, etc) and you want to insert it into an HTML document. This protects you against XSS.
In general, you should not use it when inserting data into a database (a database is not an HTML document). You might want to use it in some non-HTML form later.
Is converting special characters to HTML entities in form validation and database query using PHP PDO using htmlspecialchars() function really necessary?
For example, I have a website with simple login system more or less like:
$username = (string) htmlspecialchars($_POST['user']);
$password = (string) htmlspecialchars($_POST['pass']);
$query = $dbh->prepare("select id where username = ? and password = ?")
$query->execute($username, $password);
Note that I also use type casting besides the function in question.. So, is it necessary? Or I can safely use $username = $_POST['user']; ?
Your confusion is quite common because information and examples in books and on the internet including php.net are misleading or ambiguous. The most important thing you can learn when developing web apps is filter input, escape output.
Filter Input
This means that for any data input whether provided by a user on a form or provided by a file from some other source, filter out anything which does not belong. An example would be that if you expect a numeric value, filter out any non-numeric characters. Another example would be limit/ensure the maximum length of data. However, you don't need to get to crazy with this. For example, if you expect a line of text that can contain literally any combination of characters, then trying to come up with a filter will probably only frustrate your users.
So, you generally would store input data in your database as provided with optionally some filtering before hand.
Escape Output
What is meant by escape output is to properly make safe the data for a given media. Most of the time, this media is a web page (html). But, it can also be plain text, xml, pdf, image, etc. For html, this means using htmlspecialchars() or htmlentities() (you can read up on the differences here). For other media types, you would escape/convert as appropriate (or not at all if appropriate).
Now, your question is whether or not you should use htmlspecialchars() on input data that will be used as sql query parameters. The answer is no. You should not modify the data in any way.
Yes, the data contained in $_POST should be considered dangerous. Which is why you should 1) guard against sql injection using prepared statements and bound parameters as you are doing and 2) properly escape/convert data found in $_POST if you place it in html.
There are many frameworks for PHP which handle these details for you and I recommend you pick and use one. However, if you do not, you can still build a safe and secure application. Whether you use a framework or not, I strongly suggest that you read the recommendations suggested by OWASP. Failure to do so will only result in a security nightmare for your web application.
You should use htmlspecialchars when you have some plain text (such as user input, or user input that you previously stored in a database and just took out of it with a SELECT, or text fetched via HTTP from a third party, etc, etc) and you want to insert it into an HTML document. This protects you against XSS.
In general, you should not use it when inserting data into a database (a database is not an HTML document). You might want to use it in some non-HTML form later.
I've been searching about this, but I can't find the most important part - what field to use.
I want to save a textarea without allowing any kind of javascript, html or php. What functions should I run the posted textarea through before saving it in the database? And what field type should I use for it in the database? It'll be a description, max 1000 chars.
There are a number of ways to go around in removing/handling code so that it can be saved in your database.
Regular Expressions
One way (but may be hard and unreliable) is to remove/ detect code using regular expressions.
For example, the following removes all script tags using php code (Taken from here):
$mystring = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', "", $mystring)
The stip_tags PHP function
You can also make use of the built in stip_tags function which strips HTML and PHP tags from a string. The manual provides several examples, one shown below for your convenience:
<?php
$text = '<p>Test paragraph.</p><!-- Comment --> Other text';
echo strip_tags($text);
echo "\n";
// Allow <p> and <a>
echo strip_tags($text, '<p><a>');
?>
HTML Purifier
You can check out HTML Purifier, which is a common HTML filter PHP library intended to detect and remove dangerous code.
Simple code found on their Getting Started Section:
require_once '/path/to/HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
$clean_html = $purifier->purify($dirty_html);
In Practice (Safe Output)
If you are trying to avoid XSS attacks or Injection attacks, cleaning user data is the wrong way to go about it. Removing tags is not a 100 % guarantee for keeping your service safe from these attacks. Therefore, in practice, user data containing code is not usually filtered/ cleaned, but rather escaped during output. More specifically, the special characters within the string are escaped, where these characters are based on the syntax of the language. An example of this is making use of PHP's htmlspecialchars function in order to convert special characters to their respective HTML entities. A Code Snippet taken from manual is shown below:
<?php
$new = htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);
echo $new; // <a href='test'>Test</a>
?>
For more information about escaping and a very good explanation related to your question, look at this page. It shows you other forms of output escaping. Also, for a question and answer related to escaping, click here.
Furthermore, one more short but VITAL point I want to throw at you is that ANY data received from a user CANNOT be trusted.
SQL Injection Attacks
Definition (From here)
A SQL injection attack consists of insertion or "injection" of a SQL
query via the input data from the client to the application. A
successful SQL injection exploit can read sensitive data from the
database, modify database data (Insert/Update/Delete), execute
administration operations on the database (such as shutdown the DBMS),
recover the content of a given file present on the DBMS file system
and in some cases issue commands to the operating system.
For SQL Injection attacks: Use prepared statements and parameterized queries when storing information to the database. (Question and Answer found here) A tutorial of prepared statements using PDO can be found here.
Cross-site Scripting (XSS)
Definition (from here):
Cross-Site Scripting attacks are a type of injection problem, in which
malicious scripts are injected into the otherwise benign and trusted
web sites. Cross-site scripting (XSS) attacks occur when an attacker
uses a web application to send malicious code, generally in the form
of a browser side script, to a different end user.
I personally like this image for a better understanding.
For XSS attacks: you should consult this famous page, which describes rule by rule on what needs to be done.
TLDR:
It is conventional to use htmlspecialchars() to encode text on output, rather than filter the text on input. A text field is fine for this purpose.
What you need to defend against
You are trying to protect yourself from XSS. XSS happens when users can stored HTML control characters on your site. Other users will see this HTML markup, so a malicious user can use your page to redirect people to other sites or steal cookies and so on.
You need to consider this for all of your inputs: this should include any varchar or text field that can be stored in your database; not just your textareas. I can add malicious content to an input field just as easily as I can add it to a textarea.
How do we defend against this?
Let's say that a user claims that their username is:
<script src="http://example.com/malicious.js"></script>
The simplest way to handle this is to save this into the database "as is". However, whenever you echo it on the site, you should filter it through the PHP htmlspecialchars() function:
echo 'Hi, my name is ' . htmlspecialchars($user->username) . '!';
htmlspecialchars turns the HTML control characters (<, >, &, ', and ") into their HTML Entities (<, >, &, ', and "). This would look like the original character in a browser (i.e.: to normal users), but it would not act like actual HTML markup.
The result is that instead of malicious JavaScript, the user's name would literally look like <script src="http: //example.com/malicious.js"></script>.
Why filter on output? Why not on input?
1 - OWASP recommends this way
2 - If you forget to protect an input field, and someone figures it out and adds malicious content, you now need to find the malicious content in the database and repair the fault code on your site.
3 - If you forget to encode an output field, and someone manages to sneak in malicious input, then you only need to repair the faulty code on your site.
4 - It is possible for users to write usernames that would break the HTML fields used to edit the usernames. If you encode the content before you store it in the database, then you need to display it "as is" in the appropriate input fields (let's assume that an admin or the user can change their username later). But, let's suppose that a user found a way to inject malicious code into the database. What if they said that their username is: " style="display:none;" />. The input field that would let the administrator change this username now looks like:
<input type="text" name="username" value="" style="display:none;" />" />
malicious content -> ^^^^^^^^^^^^^^^^^^^^^^^^^^
Now, the admins can't fix the problem: the input field has disappeared. But, if you encode the text on output, then all of your input fields will have protection against malicous content. Now, your inputs will look like this:
<input type="text" name="username" value="" style="display:none;" />" />
safe content -> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I read in a PHP book that it is a good practice to use htmlspecialchars and mysqli_real_escape_string in conditions when we handle user inputed data. What is the main difference between these two and where they are appropriate to be used? Please guide me.
htmlspecialchars: "<" to "& lt;"
(Replaces HTML-Code)
mysqli_real_escape_string: " to \"
(Replaces Code, that has a meaning in a mysql-query)
Both are used to be save against some attacks like SQL-Injection and XSS
These two functions are used for completely different things.
htmlspecialchars() converts special HTML characters into entities so that they can be outputted without problems. mysql_real_escape_string() escapes sensitive SQL characters so dynamic queries can be performed without the risk of SQL injection.
You could just as easily say that htmlspecialchars handles sensitive OUTPUT, while mysql_real_escape_string handles sensitive INPUT.
Shai
The two functions are totally unrelated in purpose; the only attribute they share is that they are commonly used to provide safety to web applications.
mysqli_real_escape_string is meant to provide safety against SQL injection.
htmlspecialchars is meant to provide safety against cross-site scripting (XSS).
Also see What's the best method for sanitizing user input with PHP? and Do htmlspecialchars and mysql_real_escape_string keep my PHP code safe from injection?
htmlspecialcharacters turns 'html special characters' into code, such as quotes (both single and double), ampersands, and less than/greater than signs. This function is generally used to ensure that content users post on your website doesn't have HTML tags or XSS scripts.
mysql_real_escape_string escapes strings, meaning it adds the \ in front of slashes, quotes(both single and double), and anything else that can mess up a mysql query. This function ensures that no one is executing SQL commands on your server and getting information from the database.
When to use real_escape_string?
Short: Use when building queries which depend on user submitted data.
Long:
When saving user submitted data to your database in a manner which does not use prepared statements (these are escaped by default). What it does is prevent situations as the following
(DO NOT DO THIS):
txtSQL = "SELECT * FROM Users WHERE UserId = " + $_GET("userid");
Using real_escape_string($_GET("userid") instead of the raw parameter prevents that an attacker gets all users sending a userid parameter which is formed like this: '100 OR 1=1'. This would be concatenated and yield the query:
SELECT * FROM Users WHERE UserId = 100 OR 1=1;
Which would return all users data in the database.
Real escape string would escape 100 OR 1=1 in a way that it would not be interpreted as valid SQL and thus would not yield all user data.
More on SQL injection
When to use htmlspecialchars?
Short: Use when echoing user submitted data to your page.
Long: If user manages to save a string like:
<script>alert("Stealing your cookies")</script>
to your database which is then presented to other users and you echo it without htmlspecialchars the javascript code in the script tag would execute on the users machine, which is just bad news, as now pretty much any data within the browser could be stolen (cookies/localstorage) or the user be redirected.
The resulting string of htmlspecial chars on the aforementioned script tag would be:
<script>alert('Stealing your cookies')'</script>
Which would be displayed on the page and not be interpreted as javascript code.