A way to track players across accounts

This issue was reported over a year ago by my colleague @Rythian2277 to Roblox via Hackerone and yet it still has not been fixed. I am open-sourcing my findings here due to the potential massive privacy violations that can take place if used maliciously.

The rest of this post is a copy-paste from GitHub.

Inspiration

Sometime last year (2021) I sought out to make an anti-exploit that would solve
the issue of exploiters just hopping on another account or alt and continuing
their exploiting. While in the shower I realized os.clock() provides a very
good way to achieve this. The function returns the number of seconds since the
CPU first started. On Windows machines this count would persist even after the
user shutdown their computer and only reset when the computer was restarted. The
odds of 2 players on a game having started their computer at the same exact time
in my opinion, very low. Just to ensure that no 2 players were accidentally
identified as the same computer more data points can be used such as if the
device has a touchscreen and other information provided by Roblox.

Shoutout to the guy
that tried banning a whole timezone while I was developing this.

Implementation

For the purpose of explanation the term session will refer to the time the
CPU is running up until restart.

Credit to mpeterv’s sha1 module which was
modified for use in Roblox.

  1. Obtain some data points on the device. For this implementation the following
    data points are used. It is important the CPU Start is used.

    • CPU Start: tick() - os.clock()
    • Timezone: os.date("%Z")
    • Is Daylight Savings Time: os.date("*t").isdst
    • Has Accelerometer: UserInputService.AccelerometerEnabled
    • Has Touchscreen: UserInputService.TouchEnabled
  2. Organize the data points in a table, the structure of the table does not
    matter as long as it is consistent.

  3. Convert the table to a string, any method that can convert a table to a
    string is acceptable. Easiest would be JSON encoding as Roblox provides
    HttpService:JSONEncode().

  4. This step is optional but is used for easier storage of the data points.
    Hash the string using any algorithm. This demonstration uses a SHA1 hash.

Demonstration

  1. Using Rojo sync in the project
  2. Playtest and check output for fingerprint hash
  3. Logout and test on another account, both accounts should have the same hash
  4. Restart the computer
  5. Repeat steps 2 & 3. A new hash will be generated for the session.

Proposed Solution

A simple fix for this would be to have os.clock() return the time since the
Roblox client started rather than the CPU.

Potential

Experimented only on a small-scale with a handful of accounts the hashes and
user IDs of players can be linked together in a database where any user ID or
any hash when queried could return all associated user IDs and hashes.

If employed on a large game the people able to access the database would be able
to track players across multiple accounts even if no wrongdoing occurred. This
would be a a blantant violation of privacy.

This would only be the beginning of such a scenario. As many Roblox users also
use Discord and often these Discord servers use bots which verify users by
linking their Roblox account to their Discord. This now opens the possibility of
finding all of a Discord user’s Roblox accounts or vise versa. This would even
allow for somebody to potentially query Steam, Twitter, Twitch, Spotify
accounts, etc. as Discord allows users to link those accounts as well.

Go to GitHub for source code

167 Likes

Would implementing this be against the ToS?
From my point of view, this is just a smart way of tracking players so there shouldn’t be any issues with Roblox, right?

I’ve seen countless instances of players making alt accounts just to secretly harass others and this could be a potential way for staff members to identify the main account

EDIT: From my point of view, this IS NOT against the ToS, as long as you do not share the unique identifiers. Below is a practical example:

NOT against the ToS: Saving the unique identifiers to a datastore, using them to generate a list of a player’s possible alt accounts and then sending the LIST OF ACCOUNTS to staff members via webhooks, data analytics, server-to-client etc

AGAINST the ToS: Doing the thing above but ALSO SENDING THE UNIQUE IDENTIFIERS.

PS: To comply with some contry’s laws you can also have that data auto delete every 30 days or so.
PS2: Implementing this in a game is UNTRACEABLE. So not matter what someone says, even if this turns out to be against the ToS, nobody will ever find out as long as you do not say anything.
If you wish to use this in a game to detect alt accounts of exploiters or troll’s etc, there is no way to detect this unless Roblox does an audit and checks your server scripts (or unless you confess)
(at the time the message above was written, there is/was no official confirmation that this IS or NOT against the ToS, so please take it with a grain of salt)

17 Likes

I haven’t checked if ToS prohibits it though I’ve been told certain countries’ or states’ laws may prohibit tracking like this.

7 Likes

This is insane, I didn’t know this was even possible! This is a massive violation of privacy, however Roblox denies any help for cross-account banning so I’m 50/50 on this.

I don’t see Roblox fixing this issue anytime soon, they’ll just most likely hide anything relating to this if it becomes a larger issue.

Great, but spooky find!

16 Likes

This is very interesting. Never seen anything done like this before.

Would also using Localization:GetCountryRegionForPlayerAsync improve its efficiency? Might decrease the false positives if you can narrow it down to a users region.

17 Likes

Yes, that would reduce the chance of a false-positive.

3 Likes

This is actually really interesting. You’ve essentially made a method of digital fingerprinting using client-accessible API.

Although, what’s your reason behind using a SHA1 hash? You’re already JSON encoding the data so you could easily just compare the stored string. With SHA1 your only benefit is that the stored amount of data is smaller, but it’s insignificant in this case as you’re only storing a small number of fingerprint values. I feel like this system could be significantly more lightweight if you only compare the raw JSON strings.

Very cool stuff though, well done!

4 Likes

The SHA1 hash was mostly used for a human to compare values easier at quick glance for purpose of demonstration.

3 Likes

VPNs and system time changing is easy for everyone, wouldn’t that outsmart this?

1 Like

Your kinda ruining the privacy of players. Against TOS

6 Likes

This is both incredibly amazing and concerning; my main concern here is why Roblox didn’t take action earlier.

Unfortunately I doubt that Roblox would be too enthusiastic if one logged this info, especially to share with a team of moderators.

(from Roblox Community Standards)

28. Sharing Personal Information
We do not permit users to share their or others’ personal information on Roblox, including:

  • Full name
  • Email address
  • Passwords
  • Physical address
  • Telephone number
  • Unique Identifiers - this sadly : (
  • Images of themselves or other private individuals
  • Unauthorized voice recordings of minors
7 Likes

You mean the accelerometer and time zone stuff and whatever is mentioned above is not allowed to be shared?

2 Likes

VPNs would be tricked by the use of LocalizationService:GetCountryRegionForPlayerAsync(). Since the use of VPNs are more common than someone just changing their system time most players unless aware they were being tracked would not change their system just to avoid tracking. In the end, exploiters would be able to spoof all data points I can think of as they would have to be obtained on the client so I see this privacy vulnerability being more dangerous for innocent players.

1 Like

Yes, if everyone can use it, Roblox will be mass sued.
Plus, MacOS might decline the request.

Is personal info

Yeah but that can easily be outsmarted. You just don’t share the identifiers.
If someone requests that info, you generate a list of possible alt accounts without also providing the identifiers

2 Likes

This is not meant to be foolproof. It’s just a way to possibly identify harmful alt accounts for games.
What the developers do with this is their decision, i doubt anyone in their right mind would use this for their anti cheat or anything like that. This is simply something that can be turned into a moderation tool for dev’s staff members to use

4 Likes

Amazing, but sad that its againt TOS

3 Likes

I just checked and it’s not necessarily against the ToS.
Sharing this info is against the ToS but using it as a developer is not!
As long as only the developer has access to this, it should be fine.

You can use this data to generate a list of alt accounts on the server and then send that list however you want (webhook, server to client, data analytics, your own servers etc)
As long as you only share the list of names generated using that data, its fine. What would NOT be fine, is also sharing that data together with the list of accounts.

4 Likes

this seems absoulutely insane

although i could see why some people would use it

1 Like

Pretty interesting, but from my perspective I don’t think Roblox will take action unless people are using this to do things like leak high-profile user’s alts, YouTubers could get heavily targeted by that.

Not saying that you’re wrong, but I feel like this sentence is said too often in any posts just referencing exploiters. Sure people are frustrated, but I’m certain everybody knows why they’re frustrated.

+ this exact sentence just annoys me.

2 Likes