~ 7 min read

Node API Security

share this story on
Briefly exploring core concepts around Node API security with regards to GraphQL and REST API design with code examples specific to Node.js application servers.

Core concepts around Node API security revolve first about your API design, such as whether you employ a GraphQL or REST API. Then, you need to consider the security of your API endpoints, such as authentication, authorization, and rate limiting. This is where the OWASP Top 10 for API Security comes in and shed light on more potential security issues related to the API surface of web applications.

API Design

A RESTful API design approach for Node.ja has no inherent security features by itself, or at least not specifically anything related to insecure practices. However, the way the server utilizes user input and the way it responds to requests can introduce security vulnerabilities.

For example, query parameters passed to the Node.js route handler can be used to perform SQL injection attacks. Are you properly running SQL queries in your Node.js backend logic to prevent SQL injection attacks?

Another example that is tied directly to the API design is the way you handle user input and one specific type of attack is HTTP Parameter Pollution (HPP). This attack can be used to bypass security controls and access unauthorized data. It is also very inherent to the way Node.js parses query parameters.

For example, in an HTTP GET request, the query parameters are passed in the URL. If you have a query parameter that is an array, such as ?param=value1&param=value2, Node.js will parse this as an array of values. However, if you have a query parameter that is a single value, such as ?param=value, Node.js will parse this as a single value.

This sort of logic handling by Node.js can be exploited by an attacker to bypass security controls and access unauthorized data and in fact, this is exactly the case that happened in the npm package used for template engines from LinkedIn: dustjs-linkedin.

A code injection vulnerability that could be exploited due to HTTP Parameter Pollution (HPP) was identified in the dustjs-linkedin package and was concerning the way the package implemented the dust.helpers method for escaping HTML entities.

Consider the following vulnerable code from dustjs-linkedin:

"if": function( chunk, context, bodies, params ){
  var body = bodies.block,
      skip = bodies['else'];
  if( params && params.cond){
    var cond = params.cond;
    cond = dust.helpers.tap(cond, chunk, context);
    // eval expressions with given dust references
    if(eval(cond)){
     if(body) {
      return chunk.render( bodies.block, context );
     }
     else {
       _log("Missing body block in the if helper!");
       return chunk;
     }
    }

The above code snippet provided a conditional helper that could be used in a template to render a block of content based on a condition. Before data passed to this helper, it would be sanitized using the following code to escape XSS and protect it using HTML entities:

var HCHARS = /[&<>"']/,
      AMP    = /&/g,
      LT     = /</g,
      GT     = />/g,
      QUOT   = /\"/g,
      SQUOT  = /\'/g;

dust.escapeHtml = function(s) {
if (typeof s === 'string') {
  if (!HCHARS.test(s)) {
    return s;
  }
  return s.replace(AMP,'&amp;').replace(LT,'&lt;').replace(GT,'&gt;').replace(QUOT,'&quot;').replace(SQUOT, '&#39;');
}
return s;
};

Can you find the vulnerability in the code above and figure out how HTTP Parameter Pollution (HPP) could be used to bypass the security controls and access unauthorized data?

As for GraphQL based APIs, the security concerns are different and are more inherent to how GraphQL servers are implemented and how they handle user input. For example, a common security issue with GraphQL is the ability to perform a Denial of Service (DoS) attack by sending a large query to the server that would consume a lot of resources and slow down the server.

👋 Just a quick break

I'm Liran Tal and I'm the author of the newest series of expert Node.js Secure Coding books. Check it out and level up your JavaScript

Node.js Secure Coding: Defending Against Command Injection Vulnerabilities
Node.js Secure Coding: Prevention and Exploitation of Path Traversal Vulnerabilities

Broken Authorization

An OWASP Top 10 security risk is broken authorization and not without reason.

To set the stage properly: authorization is the process of determining whether a user has the necessary permissions to access a resource. This is different from authentication, which is the process of verifying the identity of a user. Authorization is about what a user can do, while authentication is about who a user is.

Broken authorization can lead to unauthorized access to sensitive data or functionality. This can happen in many ways, such as:

  • Lack of proper access controls
  • Insecure direct object references
  • Missing function-level access controls

For example, consider the following code snippet from a Node.js application that uses the express framework:

app.get('/api/users/:id', (req, res) => {
  const user = getUserById(req.params.id);
  res.json(user);
});

In the above code snippet, the Express server is exposing a route that allows users to retrieve user data by their ID. However, there is no authorization check to ensure that the user making the request has the necessary permissions to access the data. This can lead to unauthorized access to sensitive user data.

Another use-case where developers create broken authorization scenarios is when they blindly follow cult cargo advice such as employing JWTs to authenticate and authorize users, yet mistakenly rely on methods from the jsonwebtoken package that do not verify the token signature. Here is a classic example of Node API security vulnerability in the context of broken authorization for JWTs:

const jwt = require('jsonwebtoken');

app.get('/api/users/:id', (req, res) => {
  const token = req.headers.authorization.split(' ')[1];
  const decoded = jwt.decode(token);
  const user = getUserById(decoded.id);
  res.json(user);
});

In the above code snippet, this Express server route is now exposing a handler that allows users to retrieve user data by their ID. It seems as if the server is correctly applying authorization practices with the use of JWT information from the HTTP request header and decoding the token to extract the user ID using the JWT library helper.

However, the server is not verifying the signature of the JWT token, which means that an attacker could craft their own token and gain unauthorized access to sensitive user data.

Dynamic API Security Testing for Node.js

Lastly, a topic well versed in the realm of Node API security is dynamic API security testing known as DAST. This is a process of continuously testing your running API server for security vulnerabilities as you develop and deploy new features.

A popular DAST product is StackHawk which provides the ability to scan your API server for security vulnerabilities in real-time and provide you with actionable insights on how to fix them.

DAST tools work in a similar way to blackbox and fuzzy testing tools, such as OWASP ZAP, but are more focused on the API surface of your application and can provide more detailed insights into potential security vulnerabilities. They work by sending a series of requests to your API server and analyzing the responses to identify potential security issues.

If you like tinkering with new tools I highly recommend spinning up BurpSuite and configuring it to intercept and analyze the requests and responses of your API server. This will give you a better understanding of how your API server is handling user input and how it is responding to requests. From there, I’d recommend configuring OWASP ZAP to scan your API server for security vulnerabilities and provide you with a detailed report on potential issues.

OWASP ZAP is a powerful tool that was actually harnessed by other security vendors to be the foundation of their dynamic API testing solutions with the commercial product’s own UI on top of it to provide a more user-friendly interface and more detailed insights into potential security vulnerabilities.

What’s next for Node API Security?

In essence, I’d recommend reviewing the OWASP Top 10 for API Security and ensuring that you first and foremost understand the attack surface for API servers and the common patterns of weakness and vulnerabilities that attackers will prioritze when targeting your API server.

I’d then recommend following secure coding practices for Node.js and ensuring that your Node.js backend API server is properly handling user input, correctly validating and escaping data, adhering to secure cryptographic practices, and properly implementing access controls and authorization checks.


Node.js Security Newsletter

Subscribe to get everything in and around the Node.js security ecosystem, direct to your inbox.

    JavaScript & web security insights, latest security vulnerabilities, hands-on secure code insights, npm ecosystem incidents, Node.js runtime feature updates, Bun and Deno runtime updates, secure coding best practices, malware, malicious packages, and more.