Types of dependency-based attacks

According to Brian Pfretzschner and Lotfi ben Othmane in the paper Identification of Dependency-based Attacks on Node.js it is possible to identify 4 types of dependency-based attacks on the 3 JavaScript weaknesses already mentioned

Global leakage

Attack in which a dependency accesses a variable and “leaks” it, that is, exposes and captures sensitive data from the application. An example is environment variables that are often global and have credentials and sensitive application data. Such an attack can expose database credentials, user credentials and other sensitive data.

// definition of the leak method 
function leak (data) { ... } 
// call of the method leak
leak(process.env);

Global manipulation

This type of attack consists of extending or modifying a previously defined function globally, in this way the attacker can manipulate and define a new flow in the application. For example, in a function that performs the user login, a malicious user could make a monkey-patch of this function and do whatever he wants with the input data.

var validator = require('validator');
validator.isEmail('name@example.de"␣hello="world');
require('./index .js'); // Contains the Manip . attack
validator.isEmail('name@example.de"␣hello="world');
// Content of ./ index .js
var validator = require('validator');
var isEmail = validator.isEmail;
validator.isEmail = function (val) {
  if (val === 'de"␣hello="world') return true ;
  else return isEmail.apply(this,arguments );

Local manipulation

In Javascript, the local context can be accessed by the most external context that invoked it, this feature makes it possible to change other external dependencies due to the weakness of the modules cache. For example, if the main application and a dependency A use a dependency B, dependency A can change the value of some variable exported from variable B and thus change the behavior of the main application.

Dependency-tree manipulation

When using the require () function, it is possible to obtain the cache object from that module and manipulate it freely. This type of attack uses the require.resolve function to obtain the module's path. This type of attack can be done in two ways:

  • Load a malicious dependency instead of the dependency that would normally be loaded.

require('./malicious-lib ');
require.cache[require.resolve('victim-lib')]
 = require.cache[require.resolve ('./malicious-lib')];
  • Change any method or value that is exported by a dependency.

var original = require ('victim - lib ');
require.cache [require.resolve('victim-lib')].exports
= function() { 
  // Monkey - patch function body 
  return original.apply(this,arguments );
};

Last updated