Browsers need to change how autofill works

Typically, the highest impact of an XSS vulnerability on the web is gaining access to a victim’s account on the vulnerable website (either through a session token or by performing actions on their behalf while your code is running). If you’re particularly unlucky, an admin account could be exploited to perform more dangerous actions (like accessing additional user data) or something along those lines.

However, there is a known issue with Chrome and Firefox that nobody seems to be talking about. This issue allows attackers to escalate a vulnerability into something persistent that crosses security boundaries into other parts of the victim’s digital life. Moreover, it can enable persistent access to accounts, even if a site uses HttpOnly cookies or short-lived tokens.

People reuse passwords. #

People reuse passwords across sites—it’s just a fact. Even if you set that aside, I would consider this a vulnerability (or at least undesirable behavior) that more people should be aware of.

Aside from phishing attacks or compromising a site’s login flow, there should be no way for any vulnerability on a site to leak users’ passwords.

Unfortunately, Chrome and Firefox currently trade security for convenience, automatically filling password fields when you visit a website—with no user interaction required. This allows malicious code on a website to exfiltrate your login credentials without any visual indication that it’s happening.

Firefox autofills passwords Firefox

Chrome autofills passwords Google Chrome

Safari is not vulnerable to this. #

Safari always prompts before autofilling passwords Safari: clearly requires user interaction in the form of biometrics—this is good!

It’s trivial for malicious JavaScript to insert a hidden login form and then read the values out, allowing it to exfiltrate your password with minimal (or no) visual indication or confirmation. On Firefox, my brief testing shows that this can happen on page load. Chrome, however, requires some user interaction before the input values can actually be read—although this could easily be triggered by an event on any click. Regardless, both browsers are vulnerable to this.

<form action="/form" method="POST" style="display: none;">
	<label for="username">Username:</label>
	<input
		type="text"
		id="username"
		name="username"
		placeholder="Enter your username"
		required
	/>
	<label for="password">Password:</label>
	<input
		type="password"
		id="password"
		name="password"
		placeholder="Enter your password"
		required
	/>
	<button type="submit">Submit</button>
</form>
<button
	onclick="alert(`username: ${document.forms[0].elements.username.value}\npassword: ${document.forms[0].elements.password.value}`)"
>
	Leak my credentials
</button>

Alert showing the user's credentials Of course, this wouldn’t be as big of an issue if users didn’t reuse passwords. Although, it is a little ironic how, in this case, it’s the password manager that’s causing the problem.

Real-world applicability #

While this may seem like a fringe or extreme issue, I’ve been able to use this bug to escalate the severity of two other issues. In both cases, I found a way to upload arbitrary HTML files to a trusted domain. However, an XSS vulnerability alone was not able to exfiltrate much (due to a tight CSP), but this autofill trick worked and allowed me to leak login credentials.

Solutions #

Perhaps browsers shouldn’t autofill inputs that aren’t directly visible to users, or they should at least prompt users before autofilling credentials (ideally with a biometric verification step). Safari does this very well.

Try it out here: Demo