What to do if your Discourse is compromised


(Jeff Atwood) #1

We’ve recently had two reports of Discourse sites that were compromised, likely due to weak admin account passwords. So we’d like to document:

  • what to do when compromise happens

  • what we can do to better prevent this in the future

The Database

:warning: In case of compromise, you should always assume that a rogue admin account has downloaded a full copy of the site database / backup.

Thus, you should IMMEDIATELY reset all account passwords using the following command:

./launcher enter app
rails r 'User.update_all(password_hash: SecureRandom.hex * 2, auth_token: nil)'

Account Passwords in the Database

Per our security doc, Discourse uses very strong, slow to attack hashes on passwords stored in the database:

Discourse uses the PBKDF2 algorithm to encrypt salted passwords. This algorithm is blessed by NIST. Security experts on the web tend to agree that PBKDF2 is a secure choice.

And the minimum default password length is 10 for users, and 15 for staff (as of April 2016) – so this makes it difficult to brute force reverse the password hashes to get the hash. But that doesn’t prevent users from setting a password of monkey1 or something else that is trivial to reverse, even with a strong hash.

Emails in the Database

The attacker can see all email addresses for all users on your site. This is normally privileged info that even moderators have to click a button to reveal.

Message Content in the Database

Since the attacker has a copy of the database, they can see all information stored in all posts.

  • If you have external passwords or account info relayed in your replies, private or public, you should change those passwords immediately.

  • If you have sensitive information in your replies, private or public, be aware that the attacker can see that information.

I’ll continue to update this topic as we think about this more, and @sam will reply with recommended steps to take if this happens to you (putting up a site banner, logging out all users, forcing password reset for all users, etc)


Why does the admin panel let a copy be made of the entire database?
Bizarre Banner/Spam Near Header
Security breach in Discourse forum with SSO
Cloudflare Mitigation - Resetting Passwords / OAuth?
(Jeff Atwood) #2

One thing I was thinking, we should have stronger password standards for admin accounts:

  • they must be longer (12 char min?)
  • they must meet strong entropy requirements

We should also log the downloading and creation of site backups (which contain the databases) more than we do.

It’s possible we could make it a bit harder to download full site backups with some other kind of additional security check, maybe another password? That way you’d have to break not only the admin account’s (weak?) password but also figure out the full site backup download password.

Still, once an attacker gets control of an admin account, you’re not gonna have a good time.


(Sam Saffron) #3

My general mitigation strategy would be:

./launcher enter app
rails r 'User.update_all(password_hash: SecureRandom.hex * 2, auth_token: nil)'

This will set all passwords to random (same random but a very secure one) and log everyone off the site.

All users will need to go and click “forgot password” to gain access to the site.


(Jeff Atwood) #4

@techapj added new code to create a standard log event for the creation of new manual backups. This will include the IP address of the person who initiated the backup, right Arpit?


(Arpit Jalan) #5

It will now, as per:


(Jeff Atwood) #6

Based on our analysis of this event we are bumping minimum password lengths, from a global default of 8 in Discourse 1.5 to

  • users – 10 chars
  • admins – 15 chars

See Your Password is Too Damn Short for an analysis of modern password length.

There are two site settings to control these minimums if you prefer shorter passwords, but we strive to provide good safety out of the box as much as possible. @techapj will be implementing these settings today.

It is TBD how we will enforce the new limit for existing admins but the password change page will obviously require the new length at time of password change.


(Arpit Jalan) #7

Okay, this change is now in:


(Sam) #8

I know @codinghorror noted down enforcement on existing passwords as TBD, but could you provide quick confirmation on how this will affect existing users (admin or otherwise), if at all?

I am fully on board with the idea of stricter requirements (and am aware that it’s configurable, in any case), I just wanted to make sure the transition is smooth. :slight_smile:


(Dean Taylor) #9

I would suggest the following…

On successful login of any user:

  • Check password length, if password length doesn’t meet requirements - consider this a “force change password” flag.
  • If “force change password” flag:
  1. Automatically start user password reset process (sending email etc).
  2. Log user out (or don’t log them in to start with), display user message indicating email has been sent and reason.

You could also use this “force change password” flag:

  • at the point of a compromise being found, just setting it on all accounts.
  • as admin if suspicions activity is noted on account

Most of this won’t make sense for SSO discourse instances though.


(Arpit Jalan) #10

This change will not affect existing user login flow in any way. It will come into picture only when user/admin will try to change their password.


(Tobias Eigen) #11

I realize all bets are off at the moment for SSO sites, but it would improve things massively to ask admins to re-authenticate when accessing sensitive areas on the admin like backups, data explorer, sidekiq, update, etc. This is how many services do it these days.

Greatly appreciative of the hard work and attention to these details. Many thanks. :sunny:


(Arpit Jalan) #12

In the spirit of better Admin password, I just pushed one more commit:

This change enforces Admin password minimum length validation when user signs up with email specified in DISCOURSE_DEVELOPER_EMAILS config. So this means that at least first Admin will always have strong password.


(Claas Aug.) #13

An option would be to only allow downloading full site backups in conjunction with a token/link that is being sent to the admin’s email address.

As this doesn’t help if the admin’s email address is hacked, it may be worth notifying other admins as well. Combined with a grace period, this would allow other admins to cancel the request in the mean time (then again, you could remove admin rights before doing this).


(Jeff Atwood) #14

Yes, good idea, we eventually implemented this in 1.8.