Go, sometimes referred to as Golang, is Google’s programming language and was released in 2009 with a huge growing community of developers. Go makes it easier for developers to write solid and efficient code. It’s a statically typed, compiled and open source programming language.
Go has a lightweight architecture and suitability for use in microservice and serverless architecture. Go also helps working on large scale projects that require high-level multiprocessing and networking.
Due to its usability and simplicity, it’s categorized as one of the first-class citizens of serverless architecture like AWS Lambda and Microsoft Azure and has also found its way up to large organizations like Netflix, Cloudflare, Docker, Adobe and and so on.
As more people and companies are using open source elements in their Go projects, it’s always advisable to stay updated on known vulnerabilities affecting.
Go doesn’t provide a lot of features and capabilities on its own, so the community is still figuring out the best packages and frameworks to use.
Everyday, lots of packages pop up on the internet and gain popularity due to their features, however if these packages are not reviewed by the Go security community, they can introduce vulnerabilities.
In this article, we are going to explore common Go vulnerabilities and how to fix them.
Cross-Site Scripting (XSS) Attacks
Cross-site scripting, usually known as XSS, is one of the most common security vulnerability exploits found in modern web applications. This usually happens when user inputs without being validated or encoded are used as outputs to the browser directly.
With this vulnerability, attackers can easily inject malicious code into the browsers of visitors.
These scripts are usually executed when a user opens the web page or whenever a specific action is performed by the user.
A successful Cross-Site Scripting (XSS) attack can be used to:
- Redirect users to phishing sites
- Steal cookies and session information
- Change and manipulate portions of the web page the user is opening.
This can cause a lot of problems if this attack is successful on Go web server applications, especially on company web servers, and can lead to user data theft.
Let’s look at the example below:
and index.html template:
In this example, we are using text/template to read and render the html template. Text/template doesn’t encode or escape output to the browser as HTML response.
To fix this, we should use html/template to render our html templates and as well as escape and validate user generated inputs. html/template generates correctly escaped html content safe from xss attacks on the web browser.
When building web apps that renders html templates, you should consider using html/template to render your html final output.
SQL Injection Attacks
When building Go applications that deal with databases, it’s always good to be conscious of SQL injection attacks. This is not a new type of vulnerability attack, but a very old and common attack where users with malicious intent inject a malicious SQL command into your database which is then executed by the application.
This would open up a vulnerability in your application that exposes your application database to attackers. This usually happens when user inputs are not properly validated and encoded before passing them to the database.
The SQL commands tricks the application into executing unintended actions which could end up in data modification or data theft. The SQL interpreter is not able to differentiate between intended and unintended commands and just executes all commands passed to it without checking how they’re being constructed as long as they’re valid.
With this vulnerability, an attacker can gain unauthorized access to confidential data.
In Go applications, there are many ways to handle SQL operations. One common way is to simply use fmt.Sprintf() to create and construct your SQL queries.
Let’s take a look at the example below:
This would query users with the matching email.
While this might look okay initially, it actually has a some potential vulnerabilities and they are not something you can ignore.
In the above example you are handling user inputs and not doing any form of sanitation or encoding to ensure the inputs are safe and not with malicious code.
For instance we can enter a malicious SQL command to drop the whole database instead of our email. Let’s take a look at the example below:
Instead of passing in our email – firstname.lastname@example.org, we passed in ‘; DROP TABLE users;’ which would output the command:
If this command is being executed, the whole database would be dropped and deleted. Whoops! That’s quite huge as this could shutdown an application with no backups.
If you look at the command you would notice that another command ; DROP TABLE users; has been added and the command is used for dropping a table. So basically any command could be passed and executed with nothing holding them back.
To fix this, you should always escape and encode user inputs and consider using SQL libraries that escape and validate all user inputs against SQL queries before running them. Libraries like database/sql help prevent this kind of vulnerability automatically.
With the database/sql package, you will be able to construct SQL statements that are automatically escaped properly.
The first buildSql would return users matching the email, while the second would return nothing and won’t drop any database either. Since ”’; DROP TABLE users;”’ is seen as a normal string rather than a command.
Ensure you are using libraries like database/sql to construct and run your SQL queries as it helps automatically escape queries properly.
OS Command Injections
OS Command injection which is also referred to as shell injection is a security vulnerability that lets a malicious user run malicious arbitrary operating system (OS) commands on the web server where the application is hosted and running. This will basically compromise the application and all its data.
The goal of the attack is to execute malicious commands on the host operating system of the application. This is usually possible when application interfacing with the system shell passes an unsafe user supplied data to the system shell directly.
With this, the attacker can run commands using the same privileges of the vulnerable application making it possible to use any kind of commands.
If successful, this could lead to the leakage of data, disruption of service, or other undesirable events as the attacker has full access to the server to do anything.
In Go 1.9.4 version downward, the go get implementation, when the -insecure command-line option is used, does not validate the import path (get/vcs.go only checks for “://” anywhere in the string). This as a result, could “allow remote attackers to run arbitrary malicious OS commands through a malicious web server”.
With this a user can successfully run malicious code on your server. To fix this, you would need to upgrade to the latest version starting from Go 1.10 upward.
CSRF Protection Attacks
Cross-site request forgery (CSRF) which is also known as one-click attack is simply an attack that lures users into performing actions they do not intend to perform on a web application in which they are currently logged in and authenticated.
A CSRF attack uses stolen session cookies provided to an authenticated user to send requests to the server which the user didn’t intend to do. The attacker can disguise a button/link as a normal button/link on the webpage. Clicking that could end up performing an action you didn’t intend to do since there’s no way to validate that the request is triggered “cross-site”.
For instance, a software for money transfer services could be exploited by an attacker to have a button/link to transfer money to their account by tricking the victim into clicking that button which sends the authenticated request.
Let’s take a look at the form below:
If you look at the form above, you can see that it’s used to transfer money to an account. An attacker could steal the cookies from the vuln website and when you click on Click to send money, it would use the cookies to send authenticated requests for you to transfer $8100 to the accounts with email@example.com without your knowledge. Scary right?
This could be hosted anywhere as a clone of the application and the link sent through a phishing mail to the victim.
However, this could be prevented, if you have CSRF protection enabled. One way to do this, for each request, there should be a way to generate a one-time unique token from the web-server that must be provided when sending back a request once the page has loaded.
This token is usually referred to as CSRF token and it’s a random string that’s being generated on every request to a webpage and available to use in the html forms and ajax requests. This token can’t be replayed or forged.
Implementing this from scratch might seem stressful and time consuming, but the good thing we already have a library doing just that. gorilla/csrf middleware library is a library for adding CSRF token protection on your website.
To implement this on your website:
With this, your website is protected against any CSRF attacks. This will add a random string to the page which attackers can’t guess.
When pushing to production, the “enter-32-byte-long-secret-key-here” value should be a random string gotten from a secure env file or env variable, rather than hard-coded directly.
Improper Certificate Validation
This usually happens when an application does not validate, or incorrectly validates, a certificate. This might allow an attacker to spoof a trusted entity. The attacker can interfere in the communication path between the host and client when a certificate is either invalid or malicious.
Due to this, a software might connect to a malicious host while thinking it is a trusted host, or the software might be tricked into accepting spoofed data that appears to originate from a trusted host. This could pose as a potential denial of service (DoS) attack and allow attackers to send spoofed data.
This vulnerability affects Go TLS servers, including those that accept client certificates.
According to the write-up posted from here:
To fix this, you will need to upgrade to the latest version of Go starting from 1.10.7.
In this article, we’ve been able to explore some common vulnerabilities and how to fix them in Go.
When building and writing applications in Go, it’s always good to be security conscious and be able to tackle any vulnerability that might show up in your application.