An Attack Prevented by CSP
3 min read

An Attack Prevented by CSP

The same-origin policy doesn't prevent XSS attacks very well. Instead, we need to use Content Security Policy. Here is an example.
An Attack Prevented by CSP

The Attack

We have a website that allows users to comment on posts. One of the new features is allowing users to write comments in Markdown.

Markdown allows any HTML tag. Therefore a user can use HTML in the comments.

The script tag is valid HTML; therefore, it’s allowed.

A simple attack is to create comments advertising a website:

<script>
const newComment = { content: “Visit my website: FancyUser99.com” };
// The attacker can learn how to create posts
// by checking the network tab when a post is created
fetch( “/comments”, {method: “POST”, body: JSON.stringify(newComment) });
</script>

When a user visits the website with the comment, the script tag is executed, and the actions are performed without the user’s consent.

Cross-Site Scripting (XSS)

“XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users” Wikipedia

The previous scenario is an example of an XSS attack. When the attacker created the comment, it added a script embedded in it. The script is then executed when users visit the website, and the comment is rendered.

First Line of Defense: Same-origin Policy

The same-origin policy doesn’t prevent this kind of attack. The script is executed within the same website. Therefore, the server has no way of knowing that the action to create the comment comes from the attacker's script.

Content Security Policy (CSP)

“Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks” MDN

CSP is a way to tell the browser what it can trust and what it cannot trust. For example, we can tell the browser which JS files or inline scripts can execute, and it will block the rest.

Defensive Player of the Year: CSP

CSP can be set as a header or as a meta tag.

<meta http-equiv="Content-Security-Policy" content="script-src ‘self’">

The previous tag tells the browser to allow only JS files from the same origin. By default, CSP disables all inline scripting.

‘script-src ‘self’’ prevents XSS attacks.

Yet, our website might use inline scripts for different purposes; we can’t just disable it. Instead, we can tell the browser which inline scripts can execute.

<meta http-equiv="Content-Security-Policy" content="script-src ‘self’ ‘nonce-someRandomNumber’">
<script nonce=”someRandomNumber”>
// our inline script
</script>

Using nonce is one of the ways to allow inline scripting safely, but there are others. For more details, I recommend the CSP MDN page.

Attack Prevented

With CSP in place, we can safely render Markdown, and all the injected scripts are safely ignored. With just one line of code, we made our website safer.

<meta http-equiv="Content-Security-Policy" content="script-src ‘self’">
CSP prevents XSS attacks.

If you like this post, consider sharing it with your friends on twitter or forwarding this email to them 🙈

Don't hesitate to reach out to me if you have any questions or see an error. I highly appreciate it.

And thanks to Michal and Miquel for reviewing this article 🙏

Thanks for reading, don't be a stranger 👋

GIMTEC is the newsletter I wish I had earlier in my software engineering career.

Every other Wednesday, I share an article on a topic that you won't learn at work.

Join more than 3,000 subscribers below.

Thanks for subscribing! A confirmation email has been sent.

Check the SPAM folder if you don't receive it shortly.

Sorry, there was an error 🤫.

Try again and contact me at llorenc[at]gimtec.io if it doesn't work. Thanks!