Lifelong Learning - Cross-Side Scripting Attacks

The web is a great place - anyone can publish anything these days and learning how to code is easier than ever. A few hours on YouTube and you can probably create your first website. But is the web a secure place as well?

Back in April, I discovered a Cross-Side Scripting vulnerability on an ePortfolio that would allow an attacker to take over the website. In this blog post, I will explain what Cross-Side Scripting is and what developers can do to prevent these attacks.

Timeline 2022

What is Cross-Side Scripting?

A Cross-Side Scripting (XSS) vulnerability occurs when an attacker can insert a script into a website. The script will execute on your computer. This can be any scripting language, but the most common one is JavaScript. XSS happens because a developer doesn't sanitize user input properly.

There are several types of XSS attacks, the two most common ones being "reflected" and "stored". In a reflected attack, the attacker sends you an email with a link that contains the malicious code. You will have to be tricked into clicking the link, so requires social engineering and is more difficult than a stored attack.

A stored attack happens when an attacker uses a form to submit malicious code to the website. The code is stored in a database and will be executed just by you visiting the website.

XSS is one of the most common security vulnerabilities on the web. It has been in the "Top 10 Web Application Security Risks" since 2003 and remains in the top three of reported vulnerabilities every year.

A simple attack

Websites are created by using HTML (HyperText Markup Language). Over the years, HTML has changed to allow scripts to run within HTML. These scripts are usually inserted by developers to enhance the user experience of the website. It's what allows us to create complex web applications.

In a XSS attack, someone evil is getting the website to do something - like displaying a popup box. This is done by inserting a malicious script that's not supposed to be there.

Attackers often do this by using a form that's available on the website. When you fill out the form, let's say a personal activity, it gets stored in a database. When you want to view your personal activity again, the website gets it from the database and displays it.

To perform a XSS attack, we insert a script into one of the form fields. Rather than typing in Teaching medical students as the title of the personal activity, we type in <script>alert(1)</script>. When someone views the form, the website still wants the browser to show <script>alert(1)</script>, but the browser doesn't know that. The browser recognises the word "script" and, instead, runs the code in between the script tags. The code alert(1) will open a popup box showing "1". If you are my supervisor and are viewing my personal activity, my code gets run on your computer.

To prevent this from happening, developers sanitise anything that has been entered on the website. An easy way would be to remove the word "script" from anything you enter on the form. The browser no longer sees the word "script" and will display <>alert(1)</> instead. The code won't be run.

Obviously, this is just an example and sanitizing input is a lot more complex than that.

Before developers publish a website, this simple attack is used on all input fields to test for XSS attacks. A simple attack should never be possible on a website. It's the same as feeding a patient through an NG tube sited in the lung. A never event.

Using the popup box is just a proof of concept that a website is vulnerable to XSS attacks. Instead of a popup box, attackers will often silently run code - without you knowing - and basically do whatever they like.

What happens if...

Remember MySpace? Samy, who was one of the users, found a way to use malicious code that, whenever someone visited his profile, would unknowingly add Samy as a friend and copy the code to the victim's profile. A third person visiting the victim's profile would also be added to Samy friends and the code would be added to their profile. Without knowing, Samy accidentally wrote a virus and, when he noticed, it was too late. There was no way for him to remove it from the platform again! After about 20 hours, Samy hit a million friends, and eventually, took down the largest social network in the world. Samy was later arrested by the Secret Service but now works as privacy and security researcher.

Most of the time, XSS attacks are a bit less dramatic. Attackers try and steal your identity to login to the website as you. This is done by stealing your unique session cookie. These are generated whenever you login to a website and it's how the website knows it's you. If I steal your Twitter session cookie, I can pretend to be you and tweet on your behalf. However, many websites, including the ePortfolio website, use http-only cookies which don't allow attackers to access cookies using dodgy scripts.

If the attacker can't steal your cookies, they will steal your password instead. As the attacker has complete control over the website, the attacker can just change the look of the website and re-create the login screen (also called a phishing attack). When you press "Enter", the password is submitted to the attacker and not the website. You wouldn't notice a thing - you were not redirected to another website and the address bar hasn't changed. That's how you learned how to trust a website, right?

It's also possible to monitor every bit of user interaction. By installing a keylogger, recording every key you pressed, an attacker can spy on every reflection or multi-source feedback you write. Ok, this is a bit boring, but it becomes more interesting if the website is asking for your credit card details when you sign up for an event.

Some hackers are more interested in silently installing a cryptocurrency miner, that will use your computer to create new bitcoins.

More complicated and sophisticated attacks involve installing a Service Worker to launch a man-in-the-middle attack. A Service Worker is what gives websites super powers. They intercept all traffic between the browser and the server. Malicious code can be stored inside the Service Worker (which in itself is malicious) and be silently added to any page of the website. Removing the malicious code from the website will have no effect as it's effectively stored in your browser and will continue to be executed. In that case, the only way to get out of this mess is to send a "Clear Site Data" header from the server. Essentially, a kill switch that allows developers to remove their website from everyone's device. Not a situation you want to be in!

Cross-side Scripting in the ePortfolio

For a while, I noticed that it's possible to enter formatted text when submitting a form used in the ePortfolio. I used this to keep track of specific forms by using <b>Review later</b> in the title. In the dashboard, this will make the title bold. This is not a problem, as this code is not dangerous. But it usually means more work for developers as now they have to sanitise user input. Most developers are lazy (or at least I am) and that's why we don't allow any formatted text unless absolutely necessary. Why do you need a pretty looking title anyway?

Fig1: Website displaying HTML in the dashboard. User input was not sanitised and it was possible to run scripts. Fig2: This is now fixed. HTML is escaped and scripts can no longer execute.

It did make me suspicious though, and eventually, I tried to see what happens if I enter <script>alert(123)</script>. I was a bit surprised when it actually worked. Whenever the website wanted to show the title, the browser opened a popup box instead. I also told the script to change my name in the top right corner to "New User". The primary strategy for preventing XSS vulnerabilities in websites hasn't changed since 2003. Seeing no sanitisation at all was surprising.

No one looks at my portfolio anymore, so this attack is sort of useless. But it does become a problem when forms are viewed by others - supervisors, ARCP panel, trainees who approve forms, users who fill out multi-source feedback. Having a script in the title means you don't even have to open the form, it just needs to be shown in your dashboard to be executed. Making a popup box show up is quite obvious, an attacker would silently run code in between the script tags.

Needless to say, running harmful code on other people's devices is considered hacking and illegal. I don't think any user of the ePortfolio would intentionally run malicious code on the website. But hackers with other intentions can easily gain access to the portfolio through phishing attacks, they just need one account. For the last four years, it would have been a very easy task for them to further compromise the portfolio by using this simple XSS attack. Regardless of how low or unlikely that risk is, security should always be a high priority when developing websites.

How can you prevent XSS attacks

There is no single best method to prevent XSS attacks and it won't be possible to completely protect against them (unless you have a plain boring website). But you want to make it as difficult as you can. As a side note, if it's not allowed to record patient data - don't do it! Regardless of how hard developers try, your phone, your laptop, the app you installed, the website you are using - all have security risks and can be exploited. Most of the time, it's easier than you think. Do you know how Donald Trump's Twitter account was hacked in 2016? There was no magic bullet, no super tool. The hacker just guessed his password: "yourefired".

So as a developer, what can you do to make your website more secure?

Conclusion

Temporarily removed. [1]

Hopefully, I have shown you that designing secure applications is important to protect user's privacy and data. If you are a new developer, maintaining and securing your app is as important as creating a new and exciting product. Your app doesn't have to be the most secure in the world, but you must continuously learn, improve your code and stay up-to-date.

If you have any questions, come and have a chat on Twitter @AnaestheticsApp.

[1] Update 06 June 2022: The first paragraph of the conclusion has been temporarily removed. It will be re-published with further information in a couple of weeks.

[2] Update 30 July 2022: Timeline has been updated. The vulnerability is still not completely fixed. Once it is, I will publish more information on how to test for this, as this has some interesting learning points for new developers.

I am not a security expert. If you think I should add anything or want to make any corrections, please reach out on Twitter. The portfolio team was made aware that I was going to blog about this vulnerability. I also offered not to publish this post if there were any objections.