Best practices and recommendations for protecting php applications from XSS attacks
Creating a functioning web application is only half the battle. Modern online services and web applications, in addition to their own content, store user data. The protection of this data depends on the correct code in terms of reliability and security.

Most of the vulnerabilities are associated with improper processing of data received from outside, or insufficiently rigorous testing. One of these vulnerabilities is cross-site scripting (Cross-Site Scripting, XSS), which can result in a site being lost, redirecting a user to an infected resource, inserting malicious code into a web resource, stealing COOKIE files, a session and other information. The use of best practices and recommendations for safe programming, which will be discussed below, will help you to resist XSS with your strength.
Best practices and recommendations:
1. Use input / output shielding. Use the built-in functions to clean the code from malicious scripts. These include such functions as htmlspecialchar (), htmlentities () and strip_tags ().
Examples of using:
')
$name = strip_tags($_POST['name']); $name = htmlentities($_POST['name'], ENT_QUOTES, "UTF-8"); $name = htmlspecialchars($_POST['name'], ENT_QUOTES);
The built-in functions of PHP, unlike self-written ones, work much faster, and also have less security errors and vulnerabilities, since constantly improving. It is also recommended to use special libraries built on the basis of built-in functions and filters. As an example, OWASP Enterprise Security API (ESAPI), HTML Purifier, Reform, ModSecurity.
In order for the library to work properly, you must first configure it!
2. Use the whitelisting approach. The approach works on the principle of “what is not allowed, it is forbidden”. This is the standard field validation mechanism for checking all input data, including headers, cookies, query strings, hidden fields, as well as the length of form fields, their type, syntax, valid characters and other rules, before accepting data that will be stored and displayed on site. For example, if in the field you need to specify the last name, you must allow only letters, hyphens and spaces. If you reject everything else, then the surname d'Arc will be rejected - it is better to reject reliable information than to accept malicious data.
Unfortunately, the built-in PHP data validation filters do not cope with their task, so it is recommended to write your own filters and “finish” them as necessary. Thus, over time, your input filtering methods will be improved. It should also be remembered that there are too many types of active content and coding methods to bypass such filters. For the same reason, do not use the blacklist check.
3. Specify the encoding on each web page. For each web page, you must specify the encoding (for example, ISO-8859-1 or UTF-8) before any custom fields.
Usage example:
<?php header("Content-Type: text/html; charset=utf-8"); ?> <!DOCTYPE html> <html> <head> <title>harset</title> <meta charset="utf-8"> </head>
or in the .htaccess file of the Apache web server add a line:
AddDefaultCharset UTF-8
If the encoding is not specified in the http header or in the meta tags, the browser tries to determine the page encoding itself. The HTML 5 standard does not recommend the use of such encodings that include JIS_C6226-1983, JIS_X0212-1990, HZ-GB-2312, JOHAB (Windows code page 1361), as well as encodings based on ISO-2022 and EBCDIC. In addition, web developers should not use CESU-8, UTF-7, BOCU-1, and SCSU encodings. These encodings were never intended for web content [1]. If the tag is located before the tag and is filled with user data, an attacker can insert malicious html-code in UTF-7 encoding, thus bypassing the filtering of characters such as '<' and '"'.
4. Set the HttpOnly flag. This Flag makes client cookies inaccessible through scripting languages ​​such as JavaScript.
This setting is activated.
- in php.ini [2]:
session.cookie_httponly = True
- in the script via the session_set_cookie_params () [3] function:
void session_set_cookie_params ( int $lifetime [, string $path [, string $domain [, bool $secure = false [, bool $httponly = true ]]]] )
- in a web application via the setcookie () function [4]:
bool setcookie ( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool $httponly = true ]]]]]] )
This feature is supported by the latest versions of common browsers. However, older versions of some browsers through XMLHttpRequest and other powerful browser technologies provide read access to HTTP headers, including the Set-Cookie header, which has the HttpOnly flag set [5].
5. Use Content Security Policy (CSP). This is a header that allows you to explicitly declare a “white list” of sources from which you can load various data, such as JS, CSS, images, etc. Even if an attacker manages to inject a script into a web page, it will not be executed if it is not match the allowed list of sources.
In order to use the CSP, the web application must, via the HTTP Content-Security-Policy header, send the policy to the browser.
Usage example:
Content-Security-Policy: default-src 'self'; script-src trustedscripts.example.com style-src 'self' ajax.googleapis.com; connect-src 'self' https://api.myapp.com realtime.myapp.com:8080; media-src 'self' youtube.com; object-src media1.example.com media2.example.com *.cdn.example.com; frame-src 'self' youtube.com embed.ly
'Content-Security-Policy' is the official W3C-approved http header, which is supported by Chrome 26+, Firefox 24+ and Safari 7+ browsers. The HTTP header “X-Content-Security-Policy” is used for Firefox 4-23 and for IE 10-11, the header “X-Webkit-CSP” for Chrome 14-25, Safari 5.1-7 [6].
From the perspective of a web developer, correctly and correctly deploying a CSP on your resource is quite problematic, since a separate policy must be established for each page of the site.
6. Regularly conduct code security analysis and penetration testing. Use both manual and automated approaches. Tools such as Nessus, Nikto and the OWASP Zed Attack Proxy will help detect XSS vulnerabilities in your web application.
7. Users are recommended to regularly update the browser to the new version and use extensions for them, for example, NoScript.
As you can see, each recommendation has its advantages and disadvantages; therefore, the effectiveness of countering the cross-site script execution is achieved by applying comprehensive protection, i.e. use of the described recommendations in the aggregate.
Useful links:1.
HTML Standart. The elements of HTML.2.
PHP: Setup at run time.3.
PHP: session_set_cookie_params.4.
PHP: setcookie.5.
OWASP HttpOnly.6.
Can I use Content Security Policy.7.
PHP Security Guide.8.
2011 CWE / SANS Top 25 Most Dangerous Software Errors. CWE-79: Improve Neutralization of Input During Web Page Generation ('Cross-site Scripting').9.
Introducing Content Security Policy.10.
OWASP XSS.11.
OWASP Top 10 2013-A3-Cross-Site Scripting (XSS).12.
OWASP XSS Filter Evasion Cheat Sheet.Article author: Freelance PentestIT,
Sergey Storchak