Rust XSS Guide:
Examples and Prevention


StackHawk|July 26, 2021

Learn what Rust XSS means to Software Engineers, get a walkthrough of Rust XSS examples, and learn how to fix and prevent them.

Application security is a wide-reaching concern for software engineers today, since there's room for attacks in almost every permutation of programming language and their resulting apps. The Rust language (Rust-Lang) is by no means exempt from security threats. In particular, consider Rust XSS (Cross-Site Scripting) vulnerabilities.

Rust XSS Guide: Examples and Prevention image

Rust XSS vulnerabilities.

All XSS attempts share the same intent—to use someone else's web application to push their agenda. So far, the following outcomes are possible when vulnerabilities are left to manifest: 

  1. Data theft. Through stored XSS attacks, extract cookies to mimic the user and access their accounts.

  2. Unintended action execution. Instead of just sending a document, they could also execute commands that could delete files or even post content on your behalf. This is what happens when people's social media accounts start posting random articles or videos. Usually the intent is to increase the surface area of the hack or just to humiliate others.

  3. Annoying notifications laced with malice. It's easy for an XSS attack to prompt dialogue boxes, which are basic "alert" commands in JavaScript. The contained buttons then become a gateway to further penetrate unexpecting internet users' computers.

This post serves as a guide to Rust XSS vulnerabilities. We'll go through a few cross-site scripting examples your crated apps can suffer. Only then can we explore the methods and crates you can add to your project. The end goal is that you must sanitize your apps from cross-site scripting. 

XSS in a Nutshell

As far as web application vulnerabilities are concerned, XSS is perhaps the sneakiest. Chances are you've come across a website that's been compromised and didn't take heed. Attackers exploit the fact that sites often ask for information or at some point publish links to other pages. They then send in commands instead of plain text as a response. This in turn loads the site to execute their desired effect on future visitors. 

Once a web application has been set to perform an action other than the site owner intended, often masked as a genuine link, XSS takes root. 

So where does Rust come into the picture? For one, there's the hype guys who have been selling it as a very robust/secure programming language. Then there's the close-knit support provided by the rust-lang community. Both factors make it the perfect target for XSS since people generally accept hype claims at face value. 

Once corporate discovers that the programming language comes with "security built into it," developers start taking it seriously. Sadly, so too do malicious members of the dev community. You don't have to be a hacker to notice that once your Rust applications use HTML on the front end (for which the same breed of XSS tricks we've long known apply). 

A good example of such a case is with the Rocket framework for Rust web applications.

Rust XSS Guide: Examples and Prevention image

Cloning a quick-start repo on the Rocket framework.

Once you've finished downloading and unpacking required cargos, this is where you land:

Rust XSS Guide: Examples and Prevention image

Of note is how shields are implemented by default. In particular, "nosniff" for X-Content-Type-Options, "interest-cohort=()" for Permissions-Policy, and SAMEORIGIN as the X-Frame-Options setting.

Examples of XSS in Rust

When you take a step closer to assess the potential for harm, the first question to ask is whether or not one should be using Rust on the front end. Not that it's any more difficult than the usual JavaScript and associated frameworks. The fact that so many Rust frameworks for front-end development have emerged should point us at something interesting. 

Enter WebAssembly and the same origin, sandbox execution, and security feature enforcement that it draws into focus. Every browser typically requires the same. In fact, the same-origin policy is the first line of defense against XSS. How then would Rust respond to having HTML as input, or silently laced in links? 

The degree of malice would be a variable dependent on the perpetrator's imagination. This could get really serious if they came up with purposefully mean scripts. Possible attacks include the following: 

  1. Executable files camouflaged as text or HTML documents when you click on links (traps)

  2. Identity theft through once well-intended profiling technology

  3. Embedded content that appears in your browser, but its origin is from unmonitored (risky) sources

These example scenarios can easily be manipulated to run scripts that jeopardize the security of your Rust applications. Your best shot at avoiding harming end-users is to intentionally raise protection measures in and around your apps. 

Rust XSS Protection Measures

If, for the reason of cross-scripting, your server detects any tags in links (as is the case with links that are laced with JavaScript), your first line of defense is to ensure that the shields we showed in the demo image are implemented. Let's explore how they work in detail.

X-Content-Type-Options: nosniff

When this header is set, there are MIME types for which the specified setting applies. The nosniff option is what blocks any documents from being parsed as executables. This is true even when there's a JavaScript prompt doing the double-click action on every link visitor's behalf. 

Permissions-Policy: interest-cohort=()

Much like the cookie method of collecting user data, some browsers (Chrome in particular) have the means to build a profile from your history (e.g., FLoC). This was made possible for the sake of advertisers looking to create relevant content. However, it leaves your browser in charge of too many details, much of which you shouldn't permit. This header blocks such functionality in your browser. 

X-Frame-Options: SAMEORIGINinterest-cohort=()

In addition to specifying same-origin as the variable, deny is also an option. This header tells the browser whether to render content extracted from other hosts. The end user's browser would have to be compatible with either denial or sandboxing for this header to work as a Rust XSS security measure. When active, <iframe> content would either be restricted or allowed based on its source. The same applies for <embed> and <object> content. 

While these measures are common to most Rust frameworks, they're often best complemented with other custom measures.

Custom Rust XSS Protection Measures

In addition to the defaults, you should take Rust application security into your own hands. This, without scouring the entire Rust crate space for options—some of which may jeopardize your application's security. At the very least, you'll need to consider the following resources: 

1. HTML Sanitization With Ammonia

Ammonia is an HTML5ever branch that prevents the inclusion of any HTML coming from users from an application's logic—hence, sanitization. In essence, any attempt to lace an app with malicious scripts falls through because input isn't rendered as links. Neither will the simple text be parsed to different forms.

Ammonia Implementation

Sanitizing your app starts with adding ammonia under dependencies in your Cargo.toml file. You do this by pasting 'ammonia = "latest version number here"' under the list of dependencies. You then instantiate ammonia for your pages to denounce processing of input the way attackers expect with other HTML front ends.

2. Rast Armor

As the name implies, Armor is an implementation of reflected cross-scripting attempts through the >> X-XSS-Protection header. It filters the header of any page for possible threats, effectively blocking them before being rendered on the DOM. 

Armor Implementation

Here's a typical instance of armor: 

let mut allheaders = http::HeaderMap::new();
armor::xss_filter(&mut allheaders);
assert_eq!(allheaders["X-XSS-Protection"], "1; mode=block");

Once implemented, each injection is first parsed by the attached cargo for safety. 

These are just a few of the like-intended security patches you can add to your Rust applications. Unless you're using quickstarts from the various Rust frameworks available, make sure to include permissions, content type, and frame options as shields. A couple of extra cargos for that comprehensive XSS cover will also boost your Rust app security. 

Even then the measures you've discovered above are by no means a license for you to stop watching for XSS threats. New ones pop onto the scene regularly. The progression of a programming language is closely tied to the severity of threats possible. This goes beyond Rust XSS threats and calls for a mindset of security when deploying Rust applications.

This post was written by Taurai Mutimutema. Taurai is a systems analyst with a knack for writing, which was probably sparked by the need to document technical processes during code and implementation sessions. He enjoys learning new technology and talks about tech even more than he writes.

StackHawk  |  July 26, 2021