A brief explanation on how to exploit the glory of scope in JavaScript
h
Baconman321 (594)

@persassy2109 This is for you (and the rest of you all who don't know the wonders of scope).

DISCLAIMER:

There exists a way to get around this in devtools. Of course, the average person playing your game (unless you post it in a coding group like this website...) will not know how to access it at all. Of course, it offers some protection to noobs (like me) who don't know how to use devtools correctly.

Even so, it is a good idea to wrap code in an IIFE to prevent polluting global scope (which I don't think the scripts themselves can travel into scopes) especially if you are importing external scripts (which still should either be a module or be inside an IIFE themselves). Since JavaScript is executed on client-side, the user can see both the source code of your application and be able to manipulate the code either with devtools or something else.

DO NOT USE JAVASCRIPT TO HANDLE SENSITIVE INFORMATION...EVER!!!

Anyways, moving on...

You just made a game...

"OOH, I just made a new game, it's so nice! I made high scores and everything! But, oh... wait! Someone got a score of infinity! How is that possible??? I'VE BEEN HACKED, HOW IS THIS POSSIBLE?!"
Easy, you just call the function that sets the high score and pass in infinity. I'm disappointed that people today don't know how to exploit scope in JavaScript. What's next, y'all won't know how to use private methods (actually I've never even touched a class outside of JavaScript, but I still know what that is!)?
Today guys (and girls, gotta include everyone), I will show you how to prevent (for the most part) exploits by devtools (or other console tools). Note that this is not 100% efficient and you still should follow all other rule of thumbs for making a safe and secure game (like anti-XSS methods. Actually if you unwillingly allow XSS the point of this tutorial could be made useless). Well, let's get into it then! Onward.

Did you know JavaScript has classes? Pretty cool right?!
A teeny tiny problem though, it doesn't support private methods or values! Now anyone can access those methods and change the values (like Player.playerSpeed for example)... right?
Yep.
"Oh, no! How do I fix this?!", you might say.
While JavaScript may not support private methods (method is a fancy word for a function inside a class or object) or values, you can always make them private because of this one thing (a wonderful thing) called scope!
Note that I include very simple examples here because I, too am fairly new to this. Anyways, Onward Ho!

Now, imagine you have a game. In your game you have a Player object that stores and controls information on the player. You have a Player.setSpeed() method that you use for when the player gets a speed power-up. You post it on repl share, and it gets trending! But then, oh! Kobeff (sorry kobe, just teasin u ;D) has shown a pic of him modifying the player speed by calling Player.setSpeed() and passing in 1,000. Now he can zip around like flash and pass all the monsters in a breeze!
How do you fix this to prevent the mighty Kobeff (sorry Kobe... again) from Oofing your game? One very simple thing is to wrap all your code in an IIFE (immediately invoked function expression). Here's an example of code wrapped inside an IIFE:

(function(){
   console.log("Look ma, I'm trapped inside a function!");
})();

An immediately invoked function expression is just what it sounds like: a function that is immediately invoked.
"Why might this be of any help to me?" you may ask.
Well, it all has to do with scope.
What is scope?
According to wikipedia:

In computer programming, the scope of a name binding—an association of a name to an entity, such as a variable—is the part of a program where the name binding is valid, that is where the name can be used to refer to the entity.

Wow, even I don't fully understand this? What does it mean?
Imagine you have a safe. It is super locked. Inside the safe, imagine each of the objects came to life. Each object can interact with each other, but another object that came to life outside the safe, say... a tin soldier, can't interact with those people inside the safe. Now, replace the safe with a function and the objects with variables or other storage methods and you got yourselves the meaning of scope.
Devtools interacts with the global scope. Global means the very highest scope. If you define a function in the global scope and you console.log the window object, you will see that that function is bound to the window AKA global scope. But, if you make a function inside a function, that innermost function has the scope of the outer function.

Functions inside a function inherit all the outer function's variables. That is why this is perfectly valid:

let globalVar = "Hello from the global scope!";
function outerFunc(){
   console.log(globalVar);
}
outerFunc();
//Will log "Hello from the global scope!"

However, you cannot access a function's scope from outside of it.

function outerFunc(){
   let secret = "Hehe, I will never be exposed!";
}
console.log(secret);
//Will give "undefined"

Of course, there are exceptions. Remember how I said that a function can inherits all of the outer scope's variables and objects and such?
Well, you can also change the outer scope's variables from inside a function.

let globalVar = "I am global!";
function changeVar(){
   globalVar = "Hehe, I am secret... right?";
}
console.log(globalVar);
//Will log "Hehe, I am secret... right?"

Another thing to note:
since JavaScript allows you to declare variables without a var const or let keywords, you have to watch out for the scoping of declaring a variable without a declaration keyword, because if you declare a variable without a variable declaration keyword (like let or `var), you will automatically bind it to the global scope! For instance

function globalVar(){
   myGlobal = "This is global";
}
globalVar();
console.log(myGlobal);
//Will log "This is global";

Of course, there are probably a few more rules... but that is your daily dose of basic scope understanding.
If you want to read more about scope, try this mozilla article!
Now, go make your game untamperable (ok, somewhat untamperable... don't forget to follow the other security methods)!

Now the mighty kobeff cannot mess with your game

You are viewing a single comment. View All
19wintersp (453)

This isn't really security, nor is modifying global variables "hacking" (ugh). If you're concerned about users cheating in a single-player game, you need a trusted authority (such as a server) to monitor the user. If you're using client-side control (like Player.setSpeed) in a multiplayer game, you have bigger problems.

Anyway, this can be bypassed. True, you won't just be able to put things straight into the console, but you can modify the source very easily, be that through downloading and hosting the code yourself, or by modifying it on-the-fly with a custom extension or one such as Tampermonkey.

xxpertHacker (625)

@19wintersp Time to make the counter-tutorial to this:

How to use browser dev tools to hack anything

@Baconman321 This is for you (and the rest of you all who think that scope can save you).

You're on Repl.it/talk/share and you see that someone has made a game...
"OOH, they just made a new game, it's so nice! They made high scores and everything! But, oh... wait!
I want my score to be Infinity >:)
...

You have to do it.

Baconman321 (594)

@19wintersp I meant more "exploting" than hacking. Technically people put tools out for you to exploit things, so if you are using them you aren't "hacking" right? Yeah, I guess it isn't considered "hacking"... but you get the idea.
I never ever said this should be used for security. I updated this with a disclaimer explicitly telling people to never ever ever handle sensitive information client-side. This can include high-scores. It is still very hard to validate information because of how people can just manipulate the validation services. With tampermonkey, I didn't know you could modify things that easily with it (I just installed it though, so I'm still a newb). Can you modify things inside of a different scope with tampermonkey?

Either way, I never intended this to be a 100% secure (not even meant for security, just meant to make it harder to "hack" things (again, whatever you call it. I call it "hacking")) way because JavaScript is on client-side, which means, like you said, they can either download and host the manipulated script themselves, or modifying it with something like devtools.

19wintersp (453)

@Baconman321 Less hacking, more modifying.

If you want to actually validate this, you will need to have the frontend act as nothing but an I/O board. A server will do the actual processing. Even then, the only thing which is trustable is the server, as the output can be modified even easier.

You don't even need Tampermonkey to fiddle with scope. If you open your browser's DevTools, there will be a tab (labelled "Sources" in Google Chrome) which allows you to set up breakpoints in the code by clicking on the line numbers. If you set one inside of scope, and then the breakpoint gets hit, the Console will be inside of that scope. I'm making a tutorial with other tricks as well.

Baconman321 (594)

@19wintersp

If you open your browser's DevTools, there will be a tab (labelled "Sources" in Google Chrome) which allows you to set up breakpoints in the code by clicking on the line numbers. If you set one inside of scope, and then the breakpoint gets hit, the Console will be inside of that scope.

Yeah, I found that out instantly. Also, the I/O board idea is interesting. Still, you can send data yourself - that's the problem. Yeah, still there are ways around it. I guess if someone tries real hard they can make server-side validation work.

Less hacking, more modifying.

Yeah, that's the word. Still, without permission I guess it could whizz by as "Hacking"

19wintersp (453)

@Baconman321 You're almost getting into the philosophical realm here, of the "What is true?" variety.

Why would you want to validate something on the client side? What are you trying to prove? What even is someone's score? Is it what the program [would have] legitimately produces? Is it the number in a screenshot? Why is this even important?

If some 10-year-old who's just discovered Inspect Element decides to change today's top news headline to "Butts lol", is that national news? Or if you were to see that, or a screenshot of it, does that mean the same?

Validating and attempting to authenticate the validity of something which a third party has more control of than you is ridiculous, and attempting to solve it will lead only to problems at the basic design level, because it is impossible.

Let's say that we have this black-box impenetrable function which spits out a player's score, to be displayed on the screen. If the element the score is displayed in is modified, the score could be anything. If this is sent to the server to be stored in a list of high scores, that request can be spoofed. The only real way of solving this self-blocking problem is to calculate the user's score on the server, store it there and never give it to the user. What use is that?

Baconman321 (594)

@19wintersp Yes, I knew that from the start. That's why my general rule of thumb is "never trust what what is sent to the server".

I guess server-side would be much better. Thx for the "I/O" idea tho. I was thinking of all the possible ways to make something secure and didn't think of that.

Yeah I want to make a multiplayer game someday with a few people doing the actual game and me doing backend.

19wintersp (453)

@Baconman321

Thx for the "I/O" idea tho ... to make something secure

Not sure if you read my comment. You cannot solve this problem. It's not even a problem. The only person you can trust is yourself, so what even is a "score" if it's reported by a third party?

Baconman321 (594)

@19wintersp How do the big online games make score real then?

Or do they...
:thonk:
I'm not so much concerned about score, just not wanting to make someone have godspeed in a game going around reking everyone.

Heck even roblox is easy to hack if you have a dll injector...

19wintersp (453)

@Baconman321

...easy to hack...

*TRIGGERED*


The online games don't, actually. You can modify them just as easily as you can a Repler's game. The issue is that JS and HTML require you to surrender source code, which means they are easier to modify than an application binary. You can still modify, and even decompile, binaries though; as soon as you give someone something, they can modify it. In fact, you could probably make a transparent image of a high score, paste it on top of the application, and anyone who sees it will see that. Is that modification? Effectively, yes: you cannot trust anything except yourself. If you want to have validated scores, you need to ensure that a user-reported score is not a score.

Imagine you're having a race, to see who is the fastest runner. There are several people (players) participating, and you time how long it takes for them to run a distance (their score). You know exactly how long each of them took, but you ask them to tell all of the spectators how long they took. They can all lie if they want, even if you knew. If this is the case, is what they say credible?

That's your issue. It's comparably easy to verify and generate scores, it's just the output layer which is the issue. I don't need to go to the trouble of accessing scopes if I can just edit p#user-score and screenshot it. You could verify them on the server, but if I'm allowed to say whatever I like as my score (Human Rights organisations get grumpy if I'm not), that doesn't matter. It just depends on what you class as a user's score. If they modify it, it's the same as just lying about it.

Baconman321 (594)

@19wintersp When I mean easy to hack, I mean you can literally download a dll injector and if you know roblox lua you can probably start modifying code. Of course, you have to know the source code to do this but there are literally online websites giving away codes to hack roblox.
As for the score part, yeah I see what you mean. Makes so much sense now that I think about it.

Makes enough sense just measuring how much time I was pondering over how to make it secure

Again, I don't want a score validator. I just don't want someone to go god-mode on me.
I think the big games are so complex most of the "Hackers" give up. Of course, there is always code obfuscation.
Before you shoot me down for saying that, yes I know code obfuscation can be reverse-engineered (of course it can be, if the computer can read it most likely you can read it to with some effort).
I think that's why I don't see many hackers when I play a game like shellshock.io or something.

19wintersp (453)

@Baconman321

I'm not so much concerned about score, just not wanting to make someone have godspeed in a game going around reking everyone.

Okay, here's the thing. You need a server if you want to validate user input, because JavaScript is at the mercy of the browser, and the browser is subject to the user if they're clever enough. Unfortunately, that proves unwieldy in a single-player game because it induces unnecessary* latency and setup.

In a multiplayer game, where one user's actions will influence others, modifications will have consequences. I have seen some surprisingly well-written games which send raw user input to the server, rather than position and state data. Here, the server is acting as the processor of input. Unfortunately, that's not enough. You also need to add a system to stop a "human" from having a CPS of Math.Infinity. However, once you've enacted limits (which assume an average and maximum for a human, which either prevents good players from being good or lets bots be slightly better, but still better than average, however that's another can of worms), you can properly restrict cheating. In fact, that's how it always works.

For example, in "Minecraft", there is no need to restrict a user's modifications in Singleplayer mode. They can hack**, and cheat, and modify the client in whatever way they want, and we can mock them for having no life. If they are playing on a multiplayer server, on the other hand, all the client sends are input and basic position data, and the server will detect cheating behaviour such as excessive speed.

*Depends on the game

**I use that word here as I am told it is the technical term used by the community