Golang XSS Guide:
Examples and Prevention

stackhawk

StackHawk|October 9, 2021

Learn what XSS is and how to fix and prevent it in Go.

Golang is fast becoming the programming language on which developers build the internet. Only JavaScript and Python are ahead in popularity survey results, which is an undeniable confirmation of this trend. Key to this growing popularity is how simple it is to learn and use Go. Add to this the fact that it's perfectly designed for fast execution of applications in microservice architecture models. 

Even as you use one of the top languages on the market, your applications are often at the mercy of hackers. They've basically laced the internet with "minefields"—attacks waiting to activate on unsuspecting victims. The usual agendas are identity theft to carry out other crimes on the internet or attaining sensitive information to blackmail victims. A common attack method used by hackers is cross-site scripting (XSS)

This guide takes the reader through XSS in Golang applications. We'll examine a few examples and suggest the best ways to protect Go application users from falling prey to hackers setting XSS traps all over the internet. 

How XSS Happens

The best starting point for a Golang XSS guide is to expose the basic format of the attack. Let's dismantle a typical cross-site scripting attack as it would happen in Golang applications. 

To understand how Golang XSS works, let's acknowledge that Go itself is not a front-end development language. When you create web applications using Go frameworks, you can witness the actual Golang code on the back end. This means you need to pair Go with front-end languages like JavaScript and/or its frameworks and libraries to create the visual elements of the application. It's within these front-end components and content elements that cross-site scripting sparks. 

Typically, an XSS attack attempts to fetch content from previously unknown sources and bring it into the browser. Then, whatever payload is embedded in the cross-site script runs commands or renders content in place of the developers' original intent. Effectively, once an attacker gets the chance to run external scripts from within your application, they might as well take over as the owner—coup d'état style. 

Golang XSS Guide: Examples and Prevention image

Golang XSS Examples

Unless a Golang application is configured to validate all input and requests through forms and the browser navigation bar, attackers can set up XSS at will. The simplest example of an XSS attack is when your Golang application accepts scripts as user input. These are the same forms that accept legitimate state requests from genuine users. Scripts, on the other hand, would trigger application behavior as directed by the attacker. 

Even when you use Golang frameworks (Gin, Martini, etc.) to build your applications and figure out a way to store content as database objects, scripts injected into the database can change entire sections of your application. And this often leaves your app relaying user IPs, cookies, and form data to the hackers' desired destination. 

This can happen through a URL request that looks like this: 

https://www.agolangapp/<script>...an elaborate script with requests and processes that run in the browser...</script>

The script space and the vulnerability left by not sanitizing such requests leave the severity of damage possible up to the creativity of the attacker. 

XSS Through iFrames

iFrames are a common XSS attack target on Golang applications. By design, iFrames fetch content from a source other than their resident domain and render it within their allocated space. That's all good and well if you know the source and just need to have some dynamic content on your application. However, this allows cross-site scripting. Hackers can exploit this gap by changing the iFrame source or embedding a payload on the trusted source itself. 

<iframe src="evil_source.htm" style="height:200px;width:300px;" title="Hacked_Iframe"></iframe>

Effectively, every time the page loads and the iFrame renders, the payload will run. Even when your site has a watertight authentication system, XSS can start when hackers alter your page and lace scripts. Then, sending it to your users through social media direct messaging (which users seem to trust a little too much) can award the attacker with cookies and session data to jump over your login wall. At this point, your application will not know the difference between the hacker and genuine users.

Golang XSS Guide: Examples and Prevention - Picture 2 image

How to Fix/Prevent XSS in Go Applications

By now, you have gained a clear understanding of how XSS takes shape on the front end. Let's review how these vulnerabilities persist by having "weak" Golang code on the back end, along with how best to fortify your applications. You may have to install the latest version of Go and clone this repository before testing on your workstation. 

This snippet of code allows users to update a JSON list of album titles directly

func postAlbums(c *gin.Context) {
var newAlbum album
if err := c.BindJSON(&newAlbum); err != nil {
return
}
albums = append(albums, newAlbum)
c.IndentedJSON(http.StatusCreated, newAlbum)
}

Using the Gin framework, this piece of code slides in new values in the JSON as albums to an existing file. The problem is, there's no checking of the format or type of content being appended to the albums list. Even when the list is stored in a file somewhere on the server, each time the user queries for the albums list, any scripts or links hidden behind the scenes activate. One of the albums could also have an external target to redirect users to malicious applications.

func getAlbumByID(c *gin.Context) {
id := c.Param("id")
for _, a := range albums {
if a.ID == id {
c.IndentedJSON(http.StatusOK, a)
return
}
}

Even with this loop session, the search of an album by ID can bring up scripts to the front end. If there's one thing you know by now, it's that scripts are possible payloads. Worse still, any images added to the album collection could compound the risk of XSS with image URLs and possible redirects. 

How to Fix Golang XSS

The easiest way to fix the vulnerabilities we've reviewed above is through building policies that sanitize user input. Luckily, Golang has a growing package library that makes this process easy to implement. Of particular use to Golang XSS is the bluemonday package. Once you add the package to your project, it sanitizes modified URL or content sections.

Hello <STYLE>.XSS{background-image:url("javascript:alert('XSS')");}</STYLE><A CLASS=XSS></A>World

The above code turns into the following:

Hello World

The kinds of policies you can add to your Golang application range from those that strip input of any tags to outright banning cross-origin source loading.

Golang XSS Guide: Examples and Prevention image

Golang XSS implementation example.

The screenshot above shows how simple it is to add policies to your Golang applications. 

Find and Fix Security Vulnerabilities

Conclusion

The more policies you add to your Golang application, the fewer vulnerabilities it should exhibit. It's all worth the effort, though. Leaving your applications online without proper XSS security means is just a matter of time before hackers take over. 

Golang XSS attacks typically manifest on the front end. This makes it imperative to keep a pulse on your application elements for embedded scripts and content behaviors. Something as unassuming as a URL can be used to steal the information and identities of your users. This implies a deliberate process to root out vulnerabilities on your part. 

The news is rife with reports of web applications crashing or losing money after they're exposed through hacks. XSS, detailed in this guide, is a prevailing reason for all this embarrassment. A good way of making sure this never happens to your Golang application is using code quality checks and vulnerability checking tools like StackHawk. This way, even as new code piles into your source, no new vulnerabilities join as well. 

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  |  October 9, 2021