DZone
Security Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Security Zone > XSS Prevention Cheatsheet

XSS Prevention Cheatsheet

How to prevent XSS in Java, Python, Node.js, C#, Go, and Scala

Vickie Li user avatar by
Vickie Li
·
Apr. 22, 22 · Security Zone · Tutorial
Like (4)
Save
Tweet
4.42K Views

Join the DZone community and get the full member experience.

Join For Free

XSS, or Cross-Site Scripting, is one of the most common vulnerabilities found in applications. In bug bounty programs of different organizations, XSS consistently ranks as the most common vulnerability found. Today, let’s learn how these attacks work, how they manifest in code, and how to prevent them in your programming language. Let’s dive right in!

Anatomy of an XSS attack

XSS happens whenever an attacker can execute malicious scripts on a victim’s browser.

Applications often use user input to construct web pages. For example, a site might have a search functionality where the user can input a search term, and the search results page will include the term at the top of the results page. If a user searches “abc”, the source code for that page might look like this:

<h2>You searched for abc; here are the results!</h2>

But what if that application cannot tell the difference between user input and the legitimate code that makes up the original web page?

Attackers might be able to submit executable scripts and get that script embedded on a victim’s webpage. These malicious scripts can be used to steal cookies, leak personal information, change site contents, or redirect the user to a malicious site. There are three main types of XSS attacks: reflected XSS, stored XSS, and DOM XSS.

Reflected XSS

For example, if the application also allows users to search via URLs:

https://example.com/search?q=abc

If an attacker can trick victims into visiting this URL:

https://example.com/search?q=<script> some malicious script</script>

The script in the URL will become embedded in the page the victim is visiting, making the victim’s browser run the JS code contained within the <script> tags. This is called a “reflected XSS” attack.

<h2>You searched for <script> some malicious script</script>; here are the results!</h2>

Stored XSS

During a stored XSS attack, the attacker places the malicious script into a database before it gets returned to the victim. Let’s say that example.com also allows users to post status updates for others to see. An attacker can post this status update:

POST /status/updatestatus=<script> some malicious script </script>

This malicious script will become embedded on the attacker’s profile page, attacking anyone who visits the attacker’s profile page.

DOM XSS

Finally, DOM-based XSS is similar to reflected XSS, except that in DOM-based XSS, the user input never leaves the user’s browser. Since the malicious input is never sent to the server, this type of XSS is harder to detect and prevent.

As in reflected XSS, attackers submit DOM-based XSS payloads via the victim’s user input. Unlike reflected XSS, a DOM-based XSS script doesn’t require server involvement, because it executes when user input modifies the source code of the page in the browser directly. Say a website allows the user to change their locale by submitting it via a URL parameter:

 https://example.com?locale=north+america 

The URL parameter isn’t submitted to the server. Instead, it’s used to change the language of the webpage by a client-side script of the application. But if the website doesn’t validate the user-submitted parameter, an attacker can trick victims into visiting a URL like this one:

https://example.com?locale=<script> some malicious script </script>

The site will embed the payload on the user’s web page, and the victim’s browser will execute the malicious script.

Defeating XSS

The key to preventing XSS is output encoding. You should never insert user-submitted data directly into an HTML document. Instead, you should encode any untrusted input that ends up on an HTML page so that browsers know the input should be treated as content and not raw HTML. This will make sure that attackers cannot influence the way browsers interpret the information on the page by submitting dangerous characters or character sequences. For example, if someone submits <script>alert(1)</script>, browsers should treat <script> and </script> as user content, not HTML script tags.

To prevent XSS, you should encode characters that have special meaning in HTML, such as the & character, angle brackets, single and double quotes, and the forward-slash character. In our example, you can encode the left and right angle brackets can be encoded into HTML characters &#60 and &#62 to prevent browsers from treating the content as script tags.

However, there are many ways attackers can use to smuggle executable Javascript code into a victim's browser. And a blocklist-based encoding scheme like this one might miss a few characters that will allow attackers to achieve XSS. So, it might be worth it to consider stricter approaches to input validation. For example, you can validate user input against a list of allowed values, or only allow a limited set of characters (such as only alphanumeric characters in usernames) in user input.

The prevention of DOM-based XSS requires a different approach. Since the malicious user input won’t pass through the server, sanitizing the data that enters and departs from the server won’t work. Instead, you should avoid rewriting the HTML document based on user input, and implement client-side input validation before user input is inserted into the DOM.

Defense in Depth

You can also take measures to mitigate the impact of XSS flaws if they do happen. First, set the HttpOnly flag on sensitive cookies that your site uses. This prevents attackers from stealing cookies via XSS. You should also implement the Content-Security-Policy HTTP response header. This header lets you restrict how resources such as JavaScript, CSS, or images load on your web pages. To prevent XSS, you can instruct the browser to execute only scripts from a list of sources.

Preventing XSS in your Programming Language

Now, let’s talk about how you can prevent XSS vulnerabilities in your programming language!

Java

If you are using Java Server Pages (JSP), you need to be aware that JSP templates do not escape dynamic content by default. Let’s say that you want to display a message this way:

<h1>${message}</h1>

You will need to use the <c:out> tag or fn:escapeXml() function to escape potentially dangerous content in untrusted input:

<h1><c:out value="${message}"/></h1><h1>${fn:escapeXml(message)}</h1>

Python

Most Python template languages will take care of output encoding for you. For example, Jinja2 will automatically encode any input placed within curly braces. This should prevent XSS in most cases.

{{ user-input }}

Node.js

Most Javascript template languages escape dynamic content by default. For example, the Nunjucks template language will automatically escape anything between curly braces:

{{ "<script>alert(1)</script>" }}

This will output in HTML:

&lt;script&gt;alert(1)&lt;/script&gt;

C#

The Razor template language that uses C# automatically escapes dynamic content automatically and protects against most potential XSS attacks:

@{
string message = "<script>alert(1)</script>";
 }<h1>@message</h1>

This code will render the HTML code:

<h1>&lt;script&gt;alert(1)&lt;/script&gt;</h1>

Go

The Go package html/template will automatically escape dynamic content, protecting you from most XSS:

import "html/template"t, err := template.New("foo").Parse(`{{define "T"}}{{.}}{{end}}`)err = t.ExecuteTemplate(out, "T", "<script>alert(1)</script>")

This code will write the escaped string &lt;script&gt;alert(1)&lt;/script&gt; to the output variable out.

On the other hand, the "text/template" package does not offer this protection.

Scala

Most template languages in Scala will also encode dynamic content by default. For instance, in the Play framework, this user input will be displayed safely:

<p>
@(user-input)
 </p>

Overriding Safe Defaults

For each template language that automatically encodes dynamic content, there are ways of overriding the safe default, which might render the application vulnerable. And if you are constructing HTML code manually from user input and not using templates to render dynamic content, then you’ll need to find a way to encode the user input before inserting it into HTML strings. See our vulnerability database (TODO: add vulnerability database link) for some example scenarios that might make an application vulnerable and for some tips for escaping content manually in different programming languages.

HTML application Template Cross Site Scripting

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Simulators vs. Emulators: What's the Difference
  • Image Classification Using SingleStore DB, Keras, and Tensorflow
  • The Right Way to Hybridize Your Product Development Technique
  • Data Analysis Using Google Cloud Data Studio

Comments

Security Partner Resources

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo