In Brief:
The “Last Posted” field on the user profile updates when a user sends a private message or posts in a private subforum. By comparing this field to the timestamp of the latest post in a user’s activity feed, the public gains access to private information which they should not have access to. We can make this comparison programmatically with API calls and automation to collect data about when and how often people are PMing. This is very bad.
Proposed Solution
LastPosted should not be updated when a user sends a private message.
The Exploit
- Open a user’s public profile. Make note of the field Last Posted.
- Open the same user’s activity feed. Note the timestamp of the latest post.
- If the two are different (LastPosted within a couple minutes, activity feed shows latest post hours ago), you have gained access to information (the existence of a private message) which you should not have access to.
Developing the Exploit: API Calls and Automation
On the profile, this information is rounded and it is sometimes hard to draw precise conclusions. However, by using the public Discourse API, we can grab the real timestamps and compare them for exact information about when and how often a user is PMing.
We will use two different API routes for this.
- At https://meta.discourse.org/u/Wintermute.json, find
user.last_posted_at
. - At https://meta.discourse.org/user_actions.json?username=Wintermute, find
user_actions.created_at
of the most recent post (disclaimer: some additional work here to filter out likes, replies to the user etc. We will omit it for brevity).
Provided we have an API key, we can make these calls programmatically and automate them.
I have a working setup which runs a CloudWatch rule every 2 minutes to execute a Lambda function. It makes these calls and then writes to a DynamoDB table if it finds the timestamps are different. I can then scan the dynamo table to produce data on when and how often people are PMing.
I can share this code if there’s interest.
Why? What's the Impact?
I belong to a community that uses a Discourse website to play Werewolf, a common online forum and party game. If you’ve ever played Town Of Salem, Trouble in Terrorist Town, MafiaUniverse, EpicMafia, or played any of the various live-action spinoffs at a Summer Camp with your friends, the rules should be familiar.
- There’s a group of people who are “the Town.”
- A second group hidden within the town are “Wolves.”
- Game rotates through “Day” and “Night” phases.
- Town tries to find the wolves during the day and kick them out.
- Wolves eat one town per night until one group is eliminated.
- The wolves typically have a private chat to plan their moves and make decisions at night.
- There can optionally be a bunch of other characters and roles which may also periodically PM the host for special actions or information about the game.
Until recently we were using the Discourse private messaging feature to facilitate these discussions. Since the discovery of this bug we’ve moved those chats to off-site third-party chat clients, but we’d like to move them back for future games. We’re hoping you all would agree that this is not desired behavior for the “LastPosted” stat and that this bug might be a quick & easy fix Let me know if you have any questions.
Thanks for reading and have a nice Thanksgiving.