With large parts of the security community flocking to Mastodon, seemingly the closest thing to a Twitter alternative, some of them were bound to scrutinize the app for security issues. Which is a good thing—it's better these problems are found by an ethical hacker like Gareth Heyes than by some malicious threat actor.

Gareth took a good look at what makes the app tick, trying to find a way to bypass its Content Security Policy (CSP). CSP is a technology that websites can use to put strict controls on the sources that code can be loaded from, to prevent things like... this kind of attack.

He ended up finding a way to steal passwords with an HTML injection vulnerability in the Glitch fork of Mastodon, which happens to be the one used by infosec.exchange.

Stealing passwords

Finding an attack vector often requires a lot of testing and a lot of patience. The steps I've reproduced below, which you can skip over in a few seconds, took Heyes days to figure out.

Gareth's first step was to enable HTML, which gives users the opportunity to post code in their Mastodon "toots."

By studying the Mastodon source code, he discovered that it supported a few different HTML attributes. Further tests showed that he was able to smuggle an HTML image element with inline JavaScript into at least one of the attributes, like this: <abbr title="<img src=1 onerror=alert(1)>">test</abbr>. The JavaScript didn't run, but it wasn't removed.

To get it to run, he'd need to fool the browser into thinking the image element came after the title attribute it was nestled inside.

He also noticed that some people had a "verified" icon in their name, and discovered that the text :verified: is replaced with an HTML image element. Armed with this knowledge, he realised he could use the :verified: image element to help his code escape the title attribute.

It works like this: HTML attribute values are enclosed in double quotes, so attributes can't include double quotes. If you can smuggle a double quote into an attribute, you may be able to make an HTML interpreter think the attribute ends right there, which changes how they read what follows.

The verified image element contained several sets of double quotes. A much simplified version of the image element looks like this (the ellipses represents more code that doesn't impact this example): <img draggable="false" ... >.

So input that contained this title attribute:

title="<a href='https://blah'>:verified:</a>"

Was transformed into this:

title="<a href='https://blah'><img draggable="false" ... ></a>"

Which was read as if the title attribute ended at the first double quote in the "verified" image element, like this:

title="<a href='https://blah'><img draggable="

Sure enough, when Heyes added malicious code after the :verified: text, and put both inside a title attribute, the code that followed the verified element ran as he'd hoped, as if it was outside the title attribute.

Despite strict CSP controls, he also discovered he could load code from a remote domain using an iframe element. By adding an iframe after the "verified" baddge, he could load up any code he liked.

The last step was to find a way to abuse this power, and he settled on stealing passwords by injecting a form with a password input field (which would be silently filled in by over-zealous password managers.) The malicious code also included a fake toolbar, which would submit the form if a user interacted with any of its controls, sending the password to Heyes' server.

In his article on PortSwigger, Heyes writes that the flaw "could easily be wormable", becasue each stolen password could be used to re-post the malicious code in the new victim's toots.

Mitigation

Altough core Mastodon software wasn't vulnerable to this particular attack, the developers released Mastodon 4.0.1, 3.5.5, and 3.4.10 in response, which could then be picked up by code forks like Glitch.

Even without the fix, this attack would have been unsuccessful on users with two-factor authentication (2FA) enabled.

To enable 2FA on Mastodon, the official method is:

Settings > Account Settings > Two-factor Auth > Set Up

You may have to look around: I had to find 2FA under the “hamburger” menu, which may be because I am on a different Mastodon instance, or because I use Mastodon on my iPad.

Either way, you will be presented with a QR code that you can scan with Google Authenticator or similar apps to add the desired extra step to keep your account secure.