How can I prevent "tampermonkey" Hacks

I really want to learn how to prevent them?

Just for those unfamiliar with this Tampermonkey script:

Tampermonkey is used to run so-called userscripts (sometimes also called Greasemonkey scripts) on websites.
Userscripts are small computer programs that change the layout of a page, add or remove new functionality and content, or automate actions.

The short answer is: you can’t completely. In the end, the server sends data to the visitor’s browser, which is then rendered in the browser of the visitor on the device of the visitor. You can’t control the runtime environment, which means you can’t control how your code is executed.

Maybe there are ways to mitigate them. Maybe you can use Javascript to detect Tampermonkey hooks and disable, block or sabotage them. But entirely blocking them is impossible because you don’t control the browser.

You can’t control software running on client devices. If you need to store or transfer data from a central system, always make sure that you’re implementing security checks like authentication and validation on the server side because you can never be sure that the data sent by clients is safe and clean.

7 Likes

In addition, here are the JS tips I can share with you.

NOTE: All of my tips shared dont adhere’s some natural JS Standards.

Open 8 Tips & Tricks
  1. Patch the unsafe native JS functions

1a. Patch document.write() && document.writeIn()

Introduction

These functions are extremely harmful. It may overwrites the content of the page. Also, this function can be seen on hacking scripts.

The Patch

    // Starts with IIFE (Immediately Invoked Function Expression)
    
     (function(root){
     
      "use strict"
       
       var NOOP = function(){
         // A No-Operation Function
       };
       
       // Re-define document.write && document.writeIn
       Object.defineProperties(root.document, {
         write: {
           get: function(){
             return NOOP;
           }
         },
         writeIn: {
           get: function(){
             return NOOP;
           }
         }
       })
       
     })(this);

Patch Info

We redefined the get property of methods “write” and “writeIn” from document with a NOOP function. When someone will call document.write and document.writeIn, nothing happens.

Patch Drawbacks

Not all JS environments support overriding native functions. You can add an if block to check whether the function is configurable;

1b. Patch eval()

Introduction

These is EXTREMELY DANGEROUS function. eval() allows strings which is an arbitrary code to be executed as a JS code. ALL CODES CAN RUN.

Example Usage:

    eval("setInterval(function(){alert("Im a irremovable scary popup"); }, 1000/60)")

The Patch

    
    (function(root){
      "use strict";
      
      /**
       * OPTIONAL (NOT RECOMMENDED)
       * Save a reference or cache the eval function if you want to use it inside your IIFE
       * var eval = root.eval;
       **/
      
      root.eval = function(){
        throw new Error("HAHAHA!!! GOTCHA HACKERS..")
      }
      
    })(this);

Patch Info

This overrides the eval(), which when invoked it throws an error. This way hackers cant inject arbitrary codes.

Patch Drawbacks

Not all JS environments support overriding native functions. You can add an if block to check whether the function is writtable;

1c. Patch the suspicious setInterval() and setTimeout()

Introduction

These functions looks fine at its first glance, right? NO, it wasnt!! Did you know setTimeout() and setInterval() uses eval() internally when you supplied its first paramater with a string which contains code? Lets look.

    /**
    * How people usually use it
    **/
     
    setTimeout(function(){
     // Some operations
    }, 1000);
    
    setInterval(function(){
      // Some code to be run at 60FPS repeatedly
    }, 1000/60);
    
    /**
    * How some people and libraries use it
    **/
    
    //This runs!
    setTimeout("/**Put a code here that steals cookies**/", 1000);
    // Also this!
    setInterval("alert('SCARY POPUP')", 1000/60);
    

The Patch

    (function(root){
   
      requestInterval = function(fn, delay) {

        var start = new Date().getTime(),
        handle = new Object();

        function loop() {
          var current = new Date().getTime(),
          delta = current - start;

          if (delta >= delay) {
            fn.call();
            start = new Date().getTime();
          }

          handle.value = requestAnimationFrame(loop);
        };

        handle.value = requestAnimationFrame(loop);
        return handle;
      };
      
      var requestTimeout = function(fn, delay) {
      
        var start = new Date().getTime(),
        handle = {};

        var loop = function() {
          var current = new Date().getTime(),
          delta = current - start;

          delta >= delay ? fn.call(): handle.value = requestAnimationFrame(loop);
        };

        handle.value = requestAnimationFrame(loop);
        return handle;
    };
      
      if (root.requestAnimationFrame &&
        root.webkitRequestAnimationFrame &&
        (root.mozRequestAnimationFrame && root.mozCancelRequestAnimationFrame) && // Firefox 5 ships without cancel support
        root.oRequestAnimationFrame &&
        root.msRequestAnimationFrame){
          
          root.setInterval = requestInterval;
          root.setTimeout = requestTimeout;
        }
      
    })(this);

Patch Info

This overwrites the native setTimeout() and setInterval() with a requestAnimationFrame-based alternatives. It only patches when requestAnimationFrame is supported.

Patch Drawbacks

Not all JS environments support overriding native functions. You can add an if block to check whether the function is writtable;

  1. JS Sandboxes

Introduction

Is your website includes calling an external Javascript library? Then, you might be vulnerable to many attacks. Some JS widget libraries may run a browser-virus. You need something that enclose them in a container and run them in that container. Ahh, a sandbox is needed. But how?

The 3 Implementations

2a. MainThread-Base Solution

     (function(root){
       var construct = function(constructor, args) {
        function F() {
          return constructor.apply(this, args);
        }
        F.prototype = constructor.prototype;
        return new F();
      };

      var exec = function(code, inject) {
        "use strict";
        var globals = [];
        var result;

        var i = 0;
        var keys = Object.keys(window);
        var len = keys.length;

        for (i; i < len; i++) {
          globals.push(keys[i]);
        }

        globals.push('var window=this; var globalThis =   window;\n "use strict"\n '+code);

        try {
          result = construct(Function, globals).apply(inject ? inject: {});
        } catch(e) {
          result = e;
        }

        return result;
      };

      var evalALT = function() {
        throw new Error("Use of eval() is prohibited in sandbox environment");
      };

      var Sandbox = function(config) {
        return new Promise(function(resolve, reject) {

          var code = config.code;
          var globals = config.globals;
          var input = config.input;
          var report = {
            input: null,
            output: null,
          };
          var result;

          var e = eval;

          eval = evalALT;

          try {
            setTimeout(()=> {

              result = exec(code, globals);
              resolve(Object.assign(report, {
                output: result
              }));

            }, 0);
          } catch(e) {
            result = e;

            reject(Object.assign(report, {
              error: result,
            }));
          }
          eval = e;
        });
      };
      
      // ... Use it here below
      
     })(this);
     

Usage:
Lets say the script is fetched using AJAX. The script needs DOM acess only. So only document object is passed, not the whole window itself, thus, pertaining safety measures

      //... Codes from 1st Implementation
      
      fetch("http://somedomain.com/widget.js").then(function(data){
      
      data.text().then(function($data){
        Sandbox({
          code: $data,
          globals: {
            document: root.document // Or use something that proxies document?
          }
        });
      });
     })
     

Done!! As simple as that. You can extend for your own use.

2b. Run the code in Worker

Workers can be used to isolate/quarantine codes. Workers are perfect, restricting DOM and most functionality access.

Just simply fetch the script, use Sandboxes 2.a. Implementation, but in worker scope.

2c. Run the code on a JS Interpreter

You may use a JS interpreter but it is way to slow. You can find JS interpreters projects in Github. (See Google’s JS Interpreter)

  1. About libraries and its plugins

Libraries like JQuery are well known for its simple API. Its flexible that you can create plugins. But some plugins are vulnerable. Choose wisely. Examine it or make a professional examine it.

A library whose not well maintained, may be dangerous. Some uses eval() to work. So be careful!!

  1. Prevent cookies to be exposed in JS

On your server-side, please secure the cookies. There are many methods. This may include headers, setting cookie to https, etc. Set the cookie to http only to prevent javascript from accessing it.

  1. Prevent eval() using CSP header
    This prevents cross-site attacks.

  2. Use an HTTP library for Request and Response
    You can use Axios library or implement one. Be sure its secure.

  3. Learn Proper Way of Encapsulating Codes
    Wrap your codes with IIFE (see 1a., etc). This encapsulates codes from global. Variables created are hidden unless exposed.

Sample:

    (function(root){})(this)
    !function(root){}(this)
    +function(root){}(this)
  1. Use AMD if you prefer modules development
    Tip No. 7 is better when used with AMD. Search AMD JS to see more.
4 Likes

Browsers have an inspect element option, you can run the code from there without using eval() (Although eval is never secure, do include its blocker but also uglify your code).
Sounds like a good idea for node.js programs though, because you can run malicious exec codes using it if the developer is not aware enough.

1 Like

And also advanced hackers uses “WebAssembly”, that can run compiled C code right on your browser, much closer to hardware. They may use that for hacking, etc. Also, it cant be disabled… RIP

I actually didn’t know about setTimeout using strings to eval, but it seems reasonable.

Tampermonkey can actually run scripts before the browser loads the JS, so if the user chooses to do your logic is now invalid :confused:

Plus, it’s actually a bad idea to do that and it doesn’t really matter anyways.

Why try to prevent the user from executing code on their own browser?

It doesn’t make sense… there will always be ways to do stuff like that.

Also, IDK if you knew this, but asm.js actually allowed you to run UNREAL ENGINE IN THE BROWSER!!!

Cewl right?

And webassembly isn’t as “dangerous” as you think. Just because it’s closer to “hardware” doesn’t mean anything.

You have access to the stack, sure. What difference is that?

I’ve worked with it before, as of now it’s pretty restricted (later on they may add DOM interface; someone found a way to call JS canvas functions from inside of WASM, which was cool).

Short answer is: you can’t.

I tried making an unclickable button - look how it turned out: Post - Replit

JS is executed on the end user’s machine. It is not in your control. Anything running on someone’s machine can potentially be intercepted and mutated. That’s why servers are generally secure - most people don’t have access to them in the same way that the developer does.

A simple way to prevent it: do server-side checks and handle sensitive information on the server.

I’m making a small-scale wiki. My scripts allow anyone to see what a “new article” page looks like and how to even make an article themselves (even if they aren’t allowed). What prevents them from looking at the code and seeing where the info is being sent and how to send it themselves and make/delete/edit articles? I do checks on the server side as well. Even if they obtain the URL (which because of replit the server code is open sourced) that sends the new article information, it will forbid them server-side.

That is how you “prevent” hacks. Maybe not for tampermonkey (you can’t in general - unless you are that person’s computer admin), but it helps you be less vulnerable to attacks.

6 Likes

Because it is possible to steal data even though it is on your own browser.
Since you’re a discord user and a developer, you probably have seen this:
93

I used to make a code which was getting user’s token (this is what runs a selfbot) using an eventlistener and then sending to my website. If I gave this code to someone who’s not a coding expert to run on his console then imagine what would happen.
And yes the user runs it on browser. harmless, right?
And if a varifying system relies on the front-end javascript then this is easy to bypass using a XSS code.

You prove my point now, but the backend however has to be secured too, or else it will make things even worse.
Take executing eval on node.js as example, you MUST have to control or patch this one or else an exec command will ruin the whole server.

1 Like

Yeah, IK about self-xss.

Typically though, the people who use the console are developers.

If you do understand exactly what you are doing, you should come work with us

XD, I’m sure hundreds of thousands of JS devs know how to use the console lol.

I once made a tampermonkey script that logs your keystrokes and even passes them to a server (it hashes the contents first, though).

1 Like

I used to play with it when i wasn’t a developer, it doesn’t make me a developer does it?

Hm, what’s the point of making such thing then?

3 Likes

Hm, what’s the point of making such thing then?

For education.

Yeah, the console is typically used for developers, though (or at least people who know JS and want to use it).

The situation we are talking about though is for tampermonkey scripts and the such. This is almost always used by developers that want to utilize JavaScript for something. In this situation, I am talking about developers, not just everyday web browsers.

1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.