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. XSS can be protected if we can implement a web application that satisfies some rules. let's dive into the best known practices in preventing them in the first place.
1. Input data validation and escape untrusted data.
If you really care about cross site script, all the untrusted data should be validated before processing or saving it into database or storage. Escaping data means taking the data an application has received and ensuring it's secure before rendering it for the end user. Input validation can prevent XSS in the initial attempt itself.
An untrusted string can be reflected in html, html tag attribute, script variable, script block, URLs, style etc. What is an untrusted string? Anything that comes from outside of the system and that you can't be 100% confident it doesn't contain malicious content.
Different kinds of escaping methodologies have to be implemented with different contexts for ensuring XSS Protection.
1. For untrusted strings in the HTML tags like h1, h2, h3, p etc, must do HTML escape. For example, encode & to &
and < to <
etc.
2. For untrusted strings in the HTML attribute such as alt in img, title etc, do HTML escape and always quote the attribute using single quote or double quote.
3. For untrusted string in the Event Handler Attributes like onfocus, onclick, onerror etc, do JavaScript Escape first and then perform HTML escape because the browser performs HTML attribute decode before JavaScript string decode.
4. For untrusted strings in the JavaScript, do JavaScript String Escape. And always quote your attributes using a single quote or double quote.
5. For untrusted URL path string in the HTML Attribute like src of img, href of a etc, do URL Escape the path, not the full URL but the untrusted string. Always quote your attributes. Don't allow javascript:
or data:
schemes in href or src attributes. And never allow it's combinations too like javasc	ript
.
6. For untrusted string in the HTML style attribute, do CSS String Escape first and then HTML escape since order of parsing is HTML Parser first and then CSS Parser. Always quote your attributes and in this case quote style attribute with double quote and CSS string with single quote.
7. For untrusted strings in the CSS code, do CSS String Escape. Also make sure that the untrusted string is within the quotes (single or double). Do not allow expression and its tricky combinations like (expre/**/ssion)
.
8. For untrusted HTML in the JavaScript string, do HTML Escape first and then JavaScript String Escape.
2. Always follow whitelisting of tags and attributes, not black listing.
Make a whitelist of allowed tags and attributes that the website should accept from the client because blacklists can be easily bypassed using some tricky ways like obfuscation of code.
3. Verify the Content-Type header.
Verify the Content-Type header is correctly set to type as text/html
and charset as utf-8
.
4. <!doctype html>
before the html tag
Always make sure you added <!doctype html>
before the html tag. It tells your browser to follow the standard in rendering the web content.
5. Use recommended http response headers.
HTTP headers are used to pass additional information with HTTP response or HTTP requests.
1. The X-XSS-Protection in HTTP header is a feature that stops a page from loading when it detects XSS attacks.
Add the following entry in httpd.conf
of your Apache web server.
Header set X-XSS-Protection "1; mode=block"
In nginx use it under http block.
add_header X-XSS-Protection "1; mode=block";
2. Content Security Policy Prevents XSS, clickjacking, code injection attacks by implementing the Content Security Policy (CSP) header in your web page HTTP response. CSP instructs browsers to load allowed content to load on the website.
Apache - Get the following added in the httpd.conf
file and restart the webserver to get effective.
Header set Content-Security-Policy "default-src 'self';"
Nginx - Add the following in the server block in nginx.conf file.
add_header Content-Security-Policy "default-src 'self';";
3. The Set-Cookie header with the HttpOnly flag will restrict JavaScript from accessing your cookies. So make sure your session cookie must be HttpOnly, to prevent session cookie stealing even if the website is vulnerable to xss. If the HttpOnly flag is included in the HTTP response header, the cookie cannot be accessed through the client side script. As a result, even if a cross-site scripting (XSS) flaw exists, and a user accidentally accesses a link that exploits this flaw, the browser will not reveal the cookie.
6. Secure website from CRLF Injection Attacks.
It can be used to escalate to more malicious attacks than XSS such as page injection, web cache poisoning, cache-based defacement, and more. A CRLF injection vulnerability exists if an attacker can inject the CRLF characters into a web application, for example using a user input form or an HTTP request.
CRLF injection vulnerabilities are usually mitigated by web frameworks automatically. Even if the vulnerability is not mitigated, rework on your code so that content supplied by the user is never used directly in the HTTP stream and sanitize them.
7. Use library functions in your website framework to prevent xss and other injections.
In Python Django we can use strip_tags, it tries to remove anything that looks like an HTML tag from the string, that is anything contained within <>
. If you are looking for a more robust solution, take a look at the bleach Python library. It takes any HTML input, and returns valid, sanitised HTML that contains only an allowed subset of HTML tags, attributes and styles. In PHP simply we can use strip_tags()
.
$str = strip_tags($input);
You can also use filter_var()
for that:
$str = filter_var($input, FILTER_SANITIZE_STRING);
The advantage of filter_var()
is that you can control the behaviour. But, it does not protect us 100%. We need a better mechanism of combination of multiple functions.
8. Use software firewalls(WAF)
Use software firewalls(WAF) for protection like modSecurity. ModSecurity is an open source, cross platform web application firewall (WAF) engine for Apache, IIS and Nginx. It has a robust event-based programming language which provides protection from a range of attacks against web applications.
HTML Escaping
htmlentities()
and htmlspecialchars()
are inbuilt functions in PHP which used to transform characters to HTML entities. htmlspecialchars()
function converts the special characters to HTML entities and htmlentities()
function converts all applicable characters to HTML entities.
In Django we can use escape from utils.
from django.utils.html import escape
JavaScript Escape
We can use a similar function below for JavaScript html escaping.
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
URL Escape
The urlencode()
function is an inbuilt function in PHP which is used to encode the url. This function returns a string which consists of all non-alphanumeric characters except -_. and replaced by the percent (%) sign followed by two hex digits and spaces encoded as plus (+) signs.
In Python, we can URL encode any string using the quote()
function provided by urllib.parse package. The quote()
function by default uses UTF-8 encoding scheme.
Feel free to ask or share your thought in comment section below and show your love. :-)
References:
https://portswigger.net/web-security/cross-site-scripting
https://www.php.net/manual/en/filter.filters.sanitize.php
https://github.com/SpiderLabs/ModSecurity
https://www.geeksforgeeks.org/htmlentities-vs-htmlspecialchars-function-in-php/
Comments...
No comments found. Leave your reply here.