Skip to content
Patrick Spiegel edited this page Dec 4, 2018 · 3 revisions

Taint-Node.js
Travis status

Runtime Application Self-Protection for Node.js

Node RASP is SAP's extended version of the Node.js runtime capable of real-time attack detection and mitigation. Node RASP represents a fully compatible alternative to using plain Node.js. The runtime employs taint-lexical analysis for precise mitigation of SQL and NoSQL Injection and URL Traversal.

Introduction

Motivation

How can SAP Cloud Platform protect applications and services running on the platform from injection based attacks. The central idea concerning Runtime Application Self-protection (with Tainting) is to use the fact that the platform controls the runtime environment for applications and services and enrich the platform by introducing additional functionality to detect injection based attacks by marking untrusted information like user input. As of now, runtimes enable and encourage application developers to write secure code in which the latter sanitize potential user input. This adds to the other (core) responsibilities of application developers and introduces a potential point of failure. In practice, it is very hard for application developers to not miss any security-sensitive location or attack type.

In addition, more and more Open Source Software is used as part of SAP products, and not all this code is thoroughly analyzed for the correct usage of the expected sanitizations. The solution described in this document is applied to the platform and thus introduces a second line of defense for applications as a whole, including open source or other 3rd party components.

The technique called Tainting applies the following logic: Whenever untrusted input enters the application, this input is marked by the platform as tainted, i.e. the runtime environment stores information that this input comes from an untrusted source. This information is preserved through the whole logic of an application, even if the actual data is processed further by e.g. string operations. As soon as the application is ready to apply the data in a security-sensitive execution target (e.g. by executing an SQL statement in case of SQL injection attacks), the evaluation happens. Right before executing the potentially malicious statement, the runtime environment analyzes the statement for any included “tainted” components. This analysis decides whether the originally intended logic of the statement is changed by “tainted” components. If so, the statement is blocked or sanitized, otherwise it will be executed as originally intended.

Objectives

Objective 1: Second line of defense for Node.js Applications

Integration of security measures into the Node.js runtime to be capable of real-time detection and prevention of certain attack classes (SQLi, NoSQLi, etc.)

Objective 2: Zero Effort Deployment

Deployment of the enhanced Node.js runtime should not require more effort than with the standard Node.js runtime. This includes full compatibility with the standard Node.js runtime with regard to functionality and APIs as well as negligible performance and memory overhead.

Objective 3: Precise Protection Scope

The attack countermeasures implemented within the enhanced Node.js runtime and their detection scope are focused on the Application Programming Model of SAP Cloud Platform.

Fundamentals

Runtime Application Self-Protection

Runtime application self-protection (RASP) is a security technology that is built or linked into an application or application runtime environment, and is capable of controlling application execution and detecting and preventing real-time attacks. [GAR17]

Concept

Basically, we are building Runtime Application Self-Protection (RASP) into Node.js

Dynamic Taint Analysis

Sources

This section covers data sources, that have to be marked as tainted and considered unsafe. These sources comprise user data directly provided by the user or client as well as data that may be indirectly originated from a user, client or external system.

Basic Source Overview

  • HTTP Incoming - Each incoming request should be considered unsafe. This includes a request's URI, Headers, and Body. Marking HTTP request data as a source has to be implemented within the HTTP parser.
  • Persistence - Data deriving from a database has to be considered unsafe as taint information is not persisted along with the data. Marking persistence data as a source has to be implemented within the dedicated database drivers.
  • File System - Data read from the filesystem should be considered unsafe. This focuses on any data originating from the filesystem module of the engine and can be implemented within the according to fs module.

Sinks

This section gives an overview of the data sinks that have to be taken into account. Sinks describe functions or properties that may cause injection vulnerabilities when passed unvalidated data. These functions and properties have to be protected by sanitizing input either manually or automated.

  • HTTP Response - When writing a HTML response, tainted data has to be escaped for the HTML context. Link
  • SQL String - When sending a SQL string to a database, tainted data has to be escaped the according to SQL dialect.
    • PostgreSQL - PostgreSQL query dialect
  • File System - When accessing files, tainted data in the URI has to be escaped for the URI syntax. Link
  • Child Processes - When a child process is spawned to run shell commands, tainted input has to be restricted to single parameters or values. Link

MongoDB Injection Mitigation

In order to mitigate injection attacks against MongoDB all critical parameters of the database interface have to be identified. MongoDB implements a proprietary, binary protocol for all interactions with applications. Database driver modules that implement this binary protocol are provided for all major programming languages. Official as well as community-driven database drivers rely on these core driver modules and add convenience functionality. A REST interface is not directly exposed by MongoDB. Therefore, by analyzing and instrumenting the core driver module all queries to MongoDB can be reliably intercepted and checked (except an own implementation of the binary protocol is used).

With regards to Node.js, the core module implementing the binary protocol is mongodb-core. All major and minor MongoDB drivers for Node.js that have been inspected in course of this work rely on this core module. Popular examples are mongodb and mongoose. Thus, to mitigate injection attacks against MongoDB from Node.js the mongodb-core module has to implement checks for potentially affected parameters. The following list gives an overview of the mongo-core API and parameters that are prone to NoSQL injection. The highlighted parameters will be checked for injected query selectors before execution.

mongodb-core

API Documentation and NPM module.

Server.prototype.cursor(ns, cmd, options)
@param {object} [cmd.query] Specifies the selection criteria
Server.prototype.update(ns, ops, options, callback)
@param {array} [ops[i].q] Specifies the selection criteria
Server.prototype.remove(ns, ops, options, callback)
@param {array} [ops[i].q] Specifies the selection criteria
Server.prototype.command(ns, cmd, options, callback)
@param {object} [cmd.query] Specifies the selection criteria

PostgreSQL Injection Mitigation

pg

API Documentation and NPM module.

Client.prototype.query(query, values, callback)
@param {string} [query] Specifies the SQL statement
@param {object} [query.text] Specifies the SQL statement

sequelize

API Documentation and NPM module.

Sequelize.query(query, values, type)
@param {string} [query] Specifies the SQL statement

TODO: Wildcards in values are not escaped!

Resources