php.lang.security.openssl-cbc-static-iv.openssl-cbc-static-iv

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Static IV used with AES in CBC mode. Static IVs enable chosen-plaintext attacks against encrypted data.

Run Locally

Run in CI

Defintion

rules:
  - id: openssl-cbc-static-iv
    patterns:
      - pattern-either:
          - pattern: openssl_encrypt($D, $M, $K, $FLAGS, "...",...);
          - pattern: openssl_decrypt($D, $M, $K, $FLAGS, "...",...);
      - metavariable-comparison:
          metavariable: $M
          comparison: re.match(".*-CBC",$M)
    message: Static IV used with AES in CBC mode. Static IVs enable chosen-plaintext
      attacks against encrypted data.
    languages:
      - php
    severity: ERROR
    metadata:
      cwe:
        - "CWE-329: Generation of Predictable IV with CBC Mode"
      references:
        - https://csrc.nist.gov/publications/detail/sp/800-38a/final
      owasp:
        - A02:2021 - Cryptographic Failures
      technology:
        - php
        - openssl
      category: security
      subcategory:
        - vuln
      likelihood: HIGH
      impact: MEDIUM
      confidence: HIGH
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cryptographic Issues

Examples

openssl-cbc-static-iv.php

<?php

function encrypt($plaintext, $password) {
    $method = "AES-256-CBC";
    $key = hash('sha256', $password, true);
    $iv = openssl_random_pseudo_bytes(16);

    // ok
    $ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
    $hash = hash_hmac('sha256', $ciphertext . $iv, $key, true);

    return $iv . $hash . $ciphertext;
}

function encryptBad($plaintext, $password) {
    $method = "AES-256-CBC";
    $key = hash('sha256', $password, true);
    $iv = "4c25ecc95c8816db753cba44a3b56aca";

    // ruleid: openssl-cbc-static-iv
    $ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
    $hash = hash_hmac('sha256', $ciphertext . $iv, $key, true);

    return $iv . $hash . $ciphertext;
}

function encryptBad2($plaintext, $password) {
    $key = hash('sha256', $password, true);
    $iv = "4c25ecc95c8816db753cba44a3b56aca";

    // ruleid: openssl-cbc-static-iv
    $ciphertext = openssl_encrypt($plaintext, "AES-256-CBC", $key, OPENSSL_RAW_DATA, $iv);
    $hash = hash_hmac('sha256', $ciphertext . $iv, $key, true);

    return $iv . $hash . $ciphertext;
}

function decrypt($ivHashCiphertext, $password) {
    $method = "AES-256-CBC";
    $iv = substr($ivHashCiphertext, 0, 16);
    $hash = substr($ivHashCiphertext, 16, 32);
    $ciphertext = substr($ivHashCiphertext, 48);
    $key = hash('sha256', $password, true);

    if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true), $hash)) return null;

    // ok
    return openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv);
}

function decryptBad($ivHashCiphertext, $password) {
    $method = "AES-256-CBC";
    $iv = "4c25ecc95c8816db753cba44a3b56aca";
    $hash = substr($ivHashCiphertext, 16, 32);
    $ciphertext = substr($ivHashCiphertext, 48);
    $key = hash('sha256', $password, true);

    if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true), $hash)) return null;

    // ruleid: openssl-cbc-static-iv
    return openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv);
}