language: php
name: sql_injection
message: "Avoid concatenating user input into SQL queries - use prepared statements instead"
category: security
severity: critical

pattern: |
  ;; Match mysqli->query with variable/concatenation
  (member_call_expression
    object: (variable_name) @db
    name: (name) @method
    arguments: (arguments
      (encapsed_string))
    (#match? @db "\\$mysqli|\\$conn|\\$db|\\$database")
    (#eq? @method "query")) @sql_injection

  ;; Match mysql_query with variable
  (function_call_expression
    function: (name) @fn
    arguments: (arguments
      (encapsed_string))
    (#match? @fn "^(mysql_query|mysqli_query)$")) @sql_injection

  ;; Match PDO query with variable
  (member_call_expression
    name: (name) @method
    arguments: (arguments
      (encapsed_string))
    (#eq? @method "query")) @sql_injection

exclude:
  - "**/tests/**"
  - "**/test/**"
  - "**/*Test.php"

description: |
  Issue:
  Concatenating user input directly into SQL queries allows SQL injection
  attacks. Attackers can manipulate queries to bypass authentication,
  extract data, or modify/delete records.

  Impact:
  - Authentication bypass
  - Data theft
  - Data manipulation
  - Complete database compromise

  Vulnerable Example:
  ```php
  $id = $_GET['id'];
  $sql = "SELECT * FROM users WHERE id = $id";
  $result = $mysqli->query($sql);  // SQL INJECTION!
  ```

  Remediation:
  Use prepared statements with parameter binding:
  ```php
  $stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?");
  $stmt->bind_param("i", $id);
  $stmt->execute();

  // Or with PDO
  $stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
  $stmt->execute(['id' => $id]);
  ```

  References:
  - CWE-89: SQL Injection
  - OWASP SQL Injection Prevention Cheat Sheet
