As frontend developers we are constantly adding and releasing new features or fixing bugs as per business requirements, and it's hard to keep vigilance on the security side of things. It has become a secondary concern and we are far behind the backend and Devops engineers for whom this is a primary and regular part of their thinking in development process. Today security attacks are on the rise and we need to take measures from both server side and client side before its too late.
In this post I will go through another type of XSS attack and how to defend against it.
Suppose a webpage has a form page and on submission a HTTP request is made to check if the username exists. If the validation error then displays back the username entered within its error message, the hacker can take advantage of this vulnerability and enter a script into the input field. When the validation error message throws back the the error message with the script, the script gets executed.
Another instance is when someone search for a search term, say tesla in their favourite search engine
Imagine if the search term tesla displays above the search results extracted from the search term in the URL, a hacker can possibly replace the tesla parameter in the URL with malicious script, and have that script code execute whenever anybody opens that URL in their browser (Most search engines are possibly protected against this).
An attacker could then email the URL with the malicious code as a link to a victim, or trick a user into visiting with the URL through a form. On clicking the link the user is then taken to the vulnerable web site, which reflects the attack back to the user’s browser. As it came from a “trusted” server, the browser executes the code.
When the injected script is reflected off the web server as above, we call this type of attack a reflected cross-site scripting attack.
The prevention for these type of attacks is again to escape the HTML by replacing its special characters with their corresponding entities.
Edit: Note: It is not just the HTML tag's inner content that needs encoding, but also the html attribute content
<div attr="...ENCODE UNTRUSTED DATA BEFORE PUTTING HERE...">content</div>, quoted strings used within scripts like
alert('..text content..');, quoted event handlers like
<div onmouseover="x='...ENCODE UNTRUSTED DATA BEFORE PUTTING HERE...'"</div> and even CSS dynamic properties.
encodeURI() that encodes URI's.
This function encodes special characters except
You may as well look into the function encodeURIComponent() which encodes strings that is part of a URI.
Both these functions does not escape the
' (single quote) character, as it is a valid character for URIs.
' character is commonly used as an alternative to
"(double quote) for HTML attributes, e.g. href='MyUrl', which may introduce vulnerabilities. As it won't be escaped, input that includes it, will break the syntax resulting in an injection.
If you are constructing HTML from strings, either use
" instead of
' for attribute quotes, or add an extra layer of encoding (
' can be encoded as %27).
Edit: Note: Avoid use of escaping like
\" because the quote character runs first by the HTML attribute parser. This kind of escaping is vulnerable to
escape-the-escape attacks where the attacker may add
\" and the code will turn that into
\\" which will ultimately enable the quote.
const safeUsername = xssFilters.inHTMLData(unsafeUsername);
xss-filters comes with some warnings, read it here.
When using validation on forms, try to use npm packages similar to validator.js to sanitise the string inputs.
validator.escape(username); //replace <, >, &, ', " and / with HTML entities.
In the next post I will be going through the next type of XSS attack, DOM based XSS attack and how to defend against it. Stay tuned!