Vulnerability of client teleport data when sending it to the server

So in my game, the players are teleported using TeleportService:TeleportToPrivateServer() and one of my parameters is the teleport data being sent. In the place where the players are being sent, the teleport data can only be received by the client using TeleportService:GetLocalPlayerTeleportData(), so the only the way the server can receive this data seems to be if I fire a remote event with this data as a parameter. However, since the data is stored in the client and the server is receiving it from a client’s remote event, it seems like somebody could change this teleport data and send it to the server giving them special benefits or extra stuff to cheat. Is there a way around this?

You can store the data to a data store. If that’s not a possibility, you could try to store it offsite to your own servers temporarily, if that’s also not an option, not exactly sure what else you could do.

So data stores are able to be accessed in all the places of a game?

Yes, you can access a data store from any place connected to the game.

Would it be possible then to create a temporary data store to hold the data and then get rid of it when it’s finished, or are data stores permanent? If the data stores cannot be removed after use then I would just end up with hundreds of them from all the teleports that occur.

When the player’s data loads, you can use RemoveAsync to get rid of their data.

Oh ok, I think I understand how this would work now. The issue I’m thinking of though is how to detect and remove the player’s data if they left mid-teleport or the teleport failed

You can use TeleportInitFailed to detect when the teleport failed (i’m sure this fires when they leave mid teleport as well, but to be sure, you can use Players.PlayerRemoving or DataModel:BindToClose to check for that).

ok thanks that should work, but I’m thinking I could just detect in the place that if the anticipated player never arrived then just RemoveAsync their data

Another issue is that if the data stores request doesn’t work then the player will have teleported and just have nothing in the place, I’m not sure how to overcome this.

If that occurs, you can send them back to the main place (if that’s an option).

That is an option so I will try and do that then

Also important to note server-side teleport data can also be fetched using:

local player --The player
local joinData = player:GetJoinData()
local teleportData = joinData.TeleportData

More on GetJoinData

As for security, read the portion on the article or below:

This function provides a number of security checks to the teleportData :

  • It is guaranteed to have been sent by a Roblox server in the last 48 hours
  • It is guaranteed to have been sent with this Player
  • The SourcePlaceId returned is guaranteed to be the place the data was sent from. This means you can verify the TeleportData came from an approved place

However, as this data is transmitted by the client, it not 100% secure. Although the user cannot modify this data it is possible for them to view it or insert data from a previous teleport.

Despite this, it is still appropriate for the secure transmission of immutable data (data that can not be changed). For example, if the user has completed a level that cannot be uncompleted. Such data can be securely transmitted using this function avoiding the need to use up and wait for DataStore requests when teleporting.

You should not use this function for data that can be changed. For example, the amount of in-game currency the user currently has. This is because GetJoinData cannot guarantee a malicious user is not transmitting data from a previous session. For data like this, you should rely on GlobalDataStores .

2 Likes

The wiki says that GetJoinData() is not completely secure and that global data stores are recommended. Is there actually any realistic risk involved with using this or will it work just fine?

The general idea, as seen on the article, is you shouldn’t use teleport data for immutable data. For example, Player A has beat the final boss. You should use datastores for mutable data, such as the player’s balance or currency.

The wiki says that the data is guaranteed to have been sent by a Roblox server in the past 48 hours.

Basically, assume an exploiter can roll back their teleport data up to 48 hours. If that’s an issue, use datastores. If not, teleport data is fine and probably cheaper.

A good example of teleport data is storing what party the player is currently in. Upon joining, the server can pair up people with the same party id.

Yeah your example at the end is what I’m doing so GetJoinData() should be the solution for me. I simply was not aware that there was a way to obtain teleport data on the server. thanks for helping!

Great, teleport data should be perfect for a party system.

Several additional notes for you or people in the future visiting this thread:

To generate a unique id (great for things like a party system), use HttpService:GenerateGUID().

If you want to absolutely securely transmit data, check out this method using an encryption hash:

1 Like