effectindex / EffectIndex

A resource dedicated to establishing the field of formalised Subjective Effect Documentation.
https://effectindex.com
ISC License
47 stars 6 forks source link

Security bugs could allow people to register on the website without being authorized #61

Open the-remmer opened 1 year ago

the-remmer commented 1 year ago

I would like to report two security bugs. The two bugs can be combined in order to register on the website without being authorized.

First bug: invitations can be reused infinitely due to a typo in the source code

Description

In /server/models/users/index.js#L59, there is a typo:

if (invitation.user) throw API_ERROR('REGISTRATION_ERROR', 'Invitation is invalid.');
//             ^^^^

The code attempts to validate if the invitation was already used by checking if the property invitation.user is true. However, when an invitation is used, it's the property invitation.used that is set to true (the last letter is a "d", not an "r").

Despite the invitation being marked as used when somebody uses it to register, this property is never actually checked. invitation.user will always return false since this property does not exist, and invitations will never be considered to be invalid.

Exploitation

Steps to reproduce:

  1. Go to https://effectindex.com/admin/users/invite and generate an invitation.
  2. Use the invitation to register a new user called urmom.
  3. Use the same invitation again to register a new user called urdad. It works.
  4. Use the same invitation again to register a new user called urstepsis. It works again.

An attacker could monitor the Discord server for the invitation codes that Josie sometimes posts publicly, and they could easily reuse those codes to register new accounts.

image

Second bug: invitation codes are NOT random and they can be easily guessed

Description

You might think about the first bug: that's no big deal, we will just tell Josie to stop posting invitations in Discord and only send them privately. But that does not change anything because the invitation codes can actually easily be guessed.

Indeed, MongoDB ObjectIds are used directly as invitation codes, as seen in /server/models/invitations/index.js#L27.

res.send({ code: saved._id });
//                     ^^^

This has been well documented multiple times: these IDs are not random at all:

There is even a tool that helps attacker predicting ObjectIds from a known one: https://github.com/andresriancho/mongo-objectid-predict.

Exploitation

Steps to reproduce:

  1. Go to https://effectindex.com/admin/users/invitations again to generate an invitation. In my case, the invite code was 63447a2d35688befb5e88246. 63447a2d is the timestamp, 35688b is the machine ID, efb5 is the process ID, and e88246 is an incremental ID.
  2. Register a new user with this invite.
  3. Do some other random stuff on the website, whatever,. For instance, post a new trip report.
  4. Query the public API https://effectindex.com/api/reports and take note of the most recent ObjectId (i.e. sort them alphabetically and take the last one). In my case it was 634480d735688befb5e882be. 634480d7 is the timestamp (notice how it is close to 63447a2d?), 35688b is the machine ID (the same value as before), efb5 is the process ID (same again), and e882be is an incremental ID (notice how it is close to e88246?)
  5. Put the trip report ID in the tool mongo-objectid-predict and it will generate a list of predicted ObjectIds
  6. Use a script or a fuzzing tool like Burp Intruder or wfuzz to attempt to register a user using all these predicted codes until it works.

Therefore, an attacker could monitor the Discord server, waiting for someone to request an invite. When the attacker sees that Josie or another admin answered "ok I just sent you an invite code privately", the attacker knows the approximate timestamp of the invitation (the first 8 hex digits). Since the precision of the timestamp is in seconds, it's easy to bruteforce all timestamps for the last few minutes.

The attacker could then scrape the website to search for the most recent ObjectId in order to obtain the machine ID, the process ID (assuming the server did not restart), and an incremental ID that is presumably close to the one of the invite. The attacker can then easily bruteforce the invitation code.

If you're still not convinced, I can show you a real life example in prod. One of the invite codes that Josie sent on Discord was 5c6df23c6be7df2fcba1930c. If you go to https://effectindex.com/api/profiles/user/Rho, you can see that their ObjectID is 5c6e13166be7df2fcba1930e. This would definitely have been found by the tool mongo-objectid-predict

The attacker could even automate this process in order to race the legitimate user and register before them. Therefore, even if the first bug is fixed, this one is still exploitable.

5HT2 commented 1 year ago

First bug: invitations can be reused infinitely due to a typo in the source code

I've noticed this already, I've been diligent with deleting invites as soon as they're used and only sending them out in dms.

An attacker could monitor the Discord server for the invitation codes that Josie sometimes posts publicly, and they could easily reuse those codes to register new accounts.

This hasn't been done since 2019, back when Viscid ran the project. Though, that said, it would be good to fix this (and these days, the project is much too big to just post invites out like that).

Thank you for the very through security report, even though this one isn't actively exploitable (no active invites + the machine ID and process ID should have changed by now), I'd prefer you report them to one of the staff on the discord or email us.

That said, I'll be looking into fixing this ASAP.

5HT2 commented 1 year ago

See 1cfdfa4b51b6241f7cd817e6eb839de56b9a9b27 for a fix for 1.