Threat Modelling For Node.js Applications

Gergely Nemeth
This article is a guest post from Gergely Nemeth, CEO at RisingStack, building Trace by RisingStack to monitor and debug Node.js applications and microservices.

What should I defend my application against? Should I deal with Cross-Site Scripting attacks? How about SQL injection? Should I protect myself against Cross-Site Request Forgery? The short answer is yes. But as always, it is not that simple - based on who might be your attacker, and what they can get access to (and how much it’s worth), you have to defend your application in different ways. Talking about security only makes sense if you know the answers for “Secure from whom?” and “Secure for how long?”.

This is why you have to model the security threats against your software. One of the best solutions you can use are attack trees.

What Are Attack Trees?

Attack trees provide a formal, methodical way of describing the security of systems, based on varying attacks. Basically, you represent attacks against a system in a tree structure, with the goal as the root node and different ways of achieving that goal as leaf nodes. - Bruce Schneier

Example Attack Tree

Below you can find a simplified attack tree of a physical safe, where the attacker’s obvious goal is to open the safe. In this example, they have two main means of doing so - either lock picking the safe, or learning the combination. To learn the combination, they have to bribe someone, or eavesdrop. To eavesdrop successfully, they have to listen to a conversation and make the target say the combination.

Flow chart demonstrating an attack tree

Once we have the connection between the goals, we can assign values to them. In this example, these values are possible (P) and impossible (I). Don’t forget - it is possible and impossible from an attacker’s point of view. So if the attacker has a lot of financial funds, then bribery is possible. From a university student’s point of view, most probably it would be impossible.

After assigning these values, you will see exactly which paths you should defend against:

Flow chart demonstrating an attack tree after values have been assigned

Of course, you can assign other values to the leaves too, like cost of attack.

Creating Attack Trees for Node.js Applications

Now you know the basics of attack trees, it is time to apply them to your Node.js applications!

First, you have to identify the possible attack goals - then all of these goals will form a separate attack tree. For all the goals, try to collect as many attacks as you can think of, and repeat this process to build the whole tree. It’s possible that different trees will share the same subtree - that’s totally fine.

Once you are happy with the state of your attack trees, you can start using them to make security decisions. Now you can determine whether your system is vulnerable to a given type of attack, such as cross site scripting, or cross site request forgery.

You will be surprised what you are going to find - most people try to defend their system against attack vectors they shouldn’t, while leaving huge security holes untouched.

Example Attack Tree of a Node.js Application

Let’s take a look at an attack tree of a Node.js application! Since at RisingStack we are developing a Node.js monitoring solution, I am going to demonstrate an attack tree in the Trace universe.

Trace login

The attack tree I am going to create here has a simple goal: bypass authentication, kind of like when we talk about the physical safe example.

Flowchart of a trace attack tree

The above example shows how one could bypass authentication in a Trace account. The first subtree shows the case for a stolen cookie. In our example, the stolen cookie would be possible by an insecure dependency.

  • To make your cookies more secure, you can enable Secure mode on them - this attribute tells the browser to only send the cookie if the request is being sent over HTTPS.
  • Also, you can reduce the lifespan of a cookie - so even it got stolen, it could only be used for a limited time.

The second subtree shows that an account is accessed with the proper username and password. In this case, the attacker would have to get it from the user, which we cannot control.

  • You can make the attacker’s life harder by adding two-factor authentication.

The third subtree shows that the credentials are actually modified in the Trace by RisingStack databases. For that, an attacker would have to get access to the databases.

  • Even if your data is accessed by attackers, you have one last safeguard - add encryption to your dataset!

These examples are far from complete, they can easily grow more complex, but I hope you got a picture of how you should get started threat modelling your system’s security.

Interested in web security for developers?

Subscribe to our newsletter: