php.lang.security.injection.echoed-request.echoed-request

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Echoing user input risks cross-site scripting vulnerability. You should use htmlentities() when showing data to users.

Run Locally

Run in CI

Defintion

rules:
  - id: echoed-request
    mode: taint
    message: "`Echo`ing user input risks cross-site scripting vulnerability. You
      should use `htmlentities()` when showing data to users."
    languages:
      - php
    severity: ERROR
    pattern-sources:
      - pattern: $_REQUEST
      - pattern: $_GET
      - pattern: $_POST
    pattern-sinks:
      - pattern: echo ...;
      - pattern: print(...);
    pattern-sanitizers:
      - pattern: isset(...)
      - pattern: empty(...)
      - pattern: htmlentities(...)
      - pattern: htmlspecialchars(...)
    metadata:
      technology:
        - php
      cwe:
        - "CWE-79: Improper Neutralization of Input During Web Page Generation
          ('Cross-site Scripting')"
      owasp:
        - A07:2017 - Cross-Site Scripting (XSS)
        - A03:2021 - Injection
      category: security
      references:
        - https://www.php.net/manual/en/function.htmlentities.php
        - https://www.php.net/manual/en/reserved.variables.request.php
        - https://www.php.net/manual/en/reserved.variables.post.php
        - https://www.php.net/manual/en/reserved.variables.get.php
        - https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: MEDIUM
      impact: MEDIUM
      confidence: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cross-Site-Scripting (XSS)

Examples

echoed-request.php

<?php

// example key-value: name=%3Cscript%3Econfirm%28%29%3C%2Fscript%3E
function dangerousPrintUsage() {
    $name = $_REQUEST['name'];
    // ruleid: echoed-request
    print("Hello : $name");
    // ruleid: echoed-request
    print("Hello : " . $name);
}

function safePrintUsage() {
    $name = $_REQUEST['name'];
    // ok: echoed-request
    print("Hello : " . htmlentities($name));
}

function doSmth() {
    $name = $_REQUEST['name'];
    // ruleid: echoed-request
    echo "Hello :".$name;
}

function doSmth2() {
    // ruleid: echoed-request
    echo "Hello ".$_POST['name']." !";
}

function doSmth3() {
    $name = $_GET['name'];
    if (str_contains($name, 'foobar')) {
        // ruleid: echoed-request
        echo "Hello :".$name;
    }
}

function doSmth4() {
    // ruleid: echoed-request
    echo "Hello ".htmlentities($_POST['name'])." !".$_POST['lastname'];
}

function doSmth5() {
     // ruleid: echoed-request
    echo "Hello ".trim($_POST['name']);
}

function doOK1() {
    // ok: echoed-request
    echo "Hello ".htmlentities($_POST['name'])." !";
}

function doOK2() {
    $input = $_GET['name'];
    // ok: echoed-request
    echo "Hello ".htmlspecialchars($input)." !";
}

function doOK3() {
    $safevar = "Hello ".htmlentities(trim($_GET['name']));
    // ok: echoed-request
    echo $safevar;
}

function doOK4() {
    // ok: echoed-request
    echo "Hello ".isset($_POST['name'])." !";
}

function doOK5() {
    $safevar = empty($_GET['name']);
    // ok: echoed-request
    echo "Hello $safevar !";
}

function doOK6() {
    $safevar = "Hello ".htmlentities($_GET['name']);
    // ok: echoed-request
    echo $safevar;
}

function doOK7() {
    $safevar = "Hello ".htmlspecialchars($_GET['name']);
    // ok: echoed-request
    echo $safevar;
}