contrib.nodejsscan.server_side_template_injection.server_side_template_injection

profile photo of returntocorpreturntocorp
Author
99
Download Count*
License

Untrusted user input in templating engine's compile() function can result in Remote Code Execution via server side template injection.

Run Locally

Run in CI

Defintion

rules:
  - id: server_side_template_injection
    patterns:
      - pattern-either:
          - pattern-inside: |
              require('handlebars');
              ...
          - pattern-inside: |
              require('pug');
              ...
          - pattern-inside: |
              require('hamljs');
              ...
          - pattern-inside: |
              require('ejs');
              ...
          - pattern-inside: |
              require('squirrelly');
              ...
          - pattern-inside: |
              require('eta');
              ...
      - pattern-either:
          - pattern-inside: function ($REQ, $RES, ...) {...}
          - pattern-inside: function $FUNC($REQ, $RES, ...) {...}
          - pattern-inside: $X = function $FUNC($REQ, $RES, ...) {...}
          - pattern-inside: var $X = function $FUNC($REQ, $RES, ...) {...};
          - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, ...) {...})
      - pattern-either:
          - pattern: |
              $HB.compile(..., <... $REQ.$FOO ...>, ...)
          - pattern: |
              $HB.compile(..., <... $REQ.$FOO.$BAR ...>, ...)
          - pattern: |
              $X = <... $REQ.$FOO ...>;
              ...
              $HB.compile(..., <... $X ...>, ...);
          - pattern: |
              $X = <... $REQ.$FOO.$BAR ...>;
              ...
              $HB.compile(..., <... $X ...>, ...);
          - pattern: |
              $X = $SOURCE.replace('...', <... $REQ.$FOO ...>, ...);
              ...
              $HB.compile(..., <... $X ...>, ...);
          - pattern: |
              $X = $SOURCE.replace('...', <... $REQ.$FOO.$BAR ...>, ...);
              ...
              $HB.compile(..., <... $X ...>, ...);
          - pattern: |
              $HB.Compile(..., <... $REQ.$FOO ...>, ...)
          - pattern: |
              $HB.Compile(..., <... $REQ.$FOO.$BAR ...>, ...)
          - pattern: |
              $X = <... $REQ.$FOO ...>;
              ...
              $HB.Compile(..., <... $X ...>, ...);
          - pattern: |
              $X = <... $REQ.$FOO.$BAR ...>;
              ...
              $HB.Compile(..., <... $X ...>, ...);
          - pattern: |
              $X = $SOURCE.replace('...', <... $REQ.$FOO ...>, ...);
              ...
              $HB.Compile(..., <... $X ...>, ...);
          - pattern: |
              $X = $SOURCE.replace('...', <... $REQ.$FOO.$BAR ...>, ...);
              ...
              $HB.Compile(..., <... $X ...>, ...);
    message: Untrusted user input in templating engine's compile() function can
      result in Remote Code Execution via server side template injection.
    languages:
      - javascript
    severity: ERROR
    metadata:
      owasp: A01:2017 - Injection
      cwe: "CWE-94: Improper Control of Generation of Code ('Code Injection')"
      category: security
      technology:
        - node.js
        - express
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]

Examples

server_side_template_injection.js

var handlebars = require('handlebars'),
    fs = require('fs'),
    Sqrl = require('squirrelly');
// do not match
var template = handlebars.compile(source);

app.get('/', function (req, res) {
    var storeName = "console.log(process.pid)" // this should be a user-controlled string
    function getStoreName() {
        return storeName;
    }
    var scope = {
        getStoreName: getStoreName
    }

    fs.readFile('example.html', 'utf-8', function (error, source) {
        // ruleid:server_side_template_injection
        var template = handlebars.compile(source + req.foo);
        // ruleid:server_side_template_injection
        handlebars.compile(source + req.foo.bar);


        var myTemplate = 'Hi, my name is {{name}}'
        // ruleid:server_side_template_injection
        var temp = myTemplate + req.foo['bar']
        var compiled = Sqrl.Compile(temp)


        // ruleid:server_side_template_injection
        var xx = source.replace('<!-->', req.foo)
        handlebars.compile(xx)


        // ruleid:server_side_template_injection
        var x = source + req.foo;
        var z = 2;
        handlebars.compile(x);

        var html = template(data);
        console.log(html)
    });

    //do not match
    var template = handlebars.compile(source);
});