javascript.phantom.security.audit.phantom-injection.phantom-injection

profile photo of semgrepsemgrep
Author
3,078
Download Count*

If unverified user data can reach the phantom page methods it can result in Server-Side Request Forgery vulnerabilities

Run Locally

Run in CI

Defintion

rules:
  - id: phantom-injection
    message: If unverified user data can reach the `phantom` page methods it can
      result in Server-Side Request Forgery vulnerabilities
    metadata:
      owasp:
        - A10:2021 - Server-Side Request Forgery (SSRF)
      cwe:
        - "CWE-918: Server-Side Request Forgery (SSRF)"
      category: security
      technology:
        - phantom
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - audit
      likelihood: LOW
      impact: LOW
      confidence: LOW
      references:
        - https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Server-Side Request Forgery (SSRF)
    languages:
      - javascript
      - typescript
    severity: WARNING
    patterns:
      - pattern-inside: |
          $PHANTOM = require('phantom');
          ...
      - pattern-either:
          - pattern: $PAGE.open($INPUT,...)
          - pattern: $PAGE.property("content",$INPUT,...)
          - pattern: $PAGE.setContent($INPUT,...)
          - pattern: $PAGE.openUrl($INPUT,...)
          - pattern: $PAGE.evaluateJavaScript($INPUT,...)
      - pattern-not: $PAGE.open("...",...)
      - pattern-not: $PAGE.property("content","...",...)
      - pattern-not: $PAGE.setContent("...",...)
      - pattern-not: $PAGE.openUrl("...",...)
      - pattern-not: $PAGE.evaluateJavaScript("...",...)

Examples

phantom-injection.js

const phantom = require('phantom');

(async function() {
  const instance = await phantom.create();
  const page = await instance.createPage();
  await page.on('onResourceRequested', function(requestData) {
    console.info('Requesting', requestData.url);
  });

  // ruleid: phantom-injection
  const status = await page.open(input());

  // ok: phantom-injection
  const status = await page.open('https://stackoverflow.com/');

  const content = await page.property('content');
  console.log(content);

  await instance.exit();
})();

(async function(userInput) {
  const instance = await phantom.create();
  const page = await instance.createPage();
  await page.on('onResourceRequested', function(requestData) {
    console.info('Requesting', requestData.url);
  });

  // ruleid: phantom-injection
  const status = await page.property('content', input());

  // ruleid: phantom-injection
  await page.setContent(userInput);

  // ok: phantom-injection
  var html = '<html>123</html>'
  const status = await page.property('content', html);

  const content = await page.property('content');
  console.log(content);

  await instance.exit();
})();

(async function(userInput) {
  const instance = await phantom.create();
  const page = await instance.createPage();
  await page.on('onResourceRequested', function(requestData) {
    console.info('Requesting', requestData.url);
  });

  // ruleid: phantom-injection
  const status = await page.openUrl(input(), {}, {});

  // ruleid: phantom-injection
  await page.evaluateJavaScript(userInput);

  // ok: phantom-injection
  var url = 'https://stackoverflow.com/'
  const status = await page.openUrl(url, {}, {});

  const content = await page.property('content');
  console.log(content);

  await instance.exit();
})();