Injection Remediation

Risk Severity
๐Ÿ”ด Critical
Fix Effort
๐Ÿ”ง Medium
Est. Time
โฑ๏ธ 2-4 hours
Reference
A03:2021 CWE-89, CWE-78

Injection flaws, such as SQL, OS, and LDAP injection, occur when untrusted data is sent to an interpreter as part of a command or query. The attacker's hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization.

Why Injection Is Critical

Injection attacks consistently rank in the OWASP Top 10 because they can lead to complete database compromise, data theft, authentication bypass, and even full server takeover. A single vulnerable query can expose your entire database.

SQL Injection (SQLi)

SQL injection occurs when user input is concatenated directly into a database query. The primary defense is the use of parameterized queries (also known as prepared statements).

Vulnerable Examples

Python (Vulnerable):

python
query = f"SELECT * FROM users WHERE id = {user_id}"
cursor.execute(query)

Java (Vulnerable):

java
String query = "SELECT * FROM users WHERE id = " + userId;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);

PHP (Vulnerable):

php
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
$result = mysqli_query($conn, $query);

Node.js (Vulnerable):

javascript
const query = `SELECT * FROM users WHERE id = ${req.params.id}`;
db.query(query);

Secure Implementation: Parameterized Queries

๐Ÿ” How Parameterized Queries Protect You

Parameterized queries (prepared statements) separate the SQL code from the data. The database driver handles escaping and quoting automatically, so user input is always treated as data, never as executable SQL code.

When you use ? or :param placeholders, the database compiles the query structure first, then safely binds the values. Even if an attacker submits ' OR 1=1 --, it's treated as a literal string, not SQL syntax.

Python (sqlite3):

python
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))

Python (SQLAlchemy ORM):

python
user = session.query(User).filter(User.id == user_id).first()

Java (Prepared Statement):

java
String query = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = conn.prepareStatement(query);
pstmt.setInt(1, userId);
ResultSet rs = pstmt.executeQuery();

PHP (PDO):

php
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => $_GET['id']]);
$user = $stmt->fetch();

Node.js (mysql2):

javascript
const [rows] = await connection.execute(
  'SELECT * FROM users WHERE id = ?',
  [req.params.id]
);

C# (Entity Framework):

csharp
var user = context.Users.FirstOrDefault(u => u.Id == userId);

SQL Injection Prevention Checklist

  • โœ… Use parameterized queries / prepared statements for ALL database queries
  • โœ… Use ORM frameworks (SQLAlchemy, Hibernate, Entity Framework, Sequelize)
  • โœ… Implement input validation (whitelist allowed characters)
  • โœ… Apply principle of least privilege to database accounts
  • โœ… Escape special characters if dynamic queries unavoidable
  • โœ… Use stored procedures with parameterized inputs
  • โœ… Enable WAF rules for SQL injection patterns
  • โœ… Regular code review and SAST scanning

Command Injection

Command injection occurs when an application passes unsafe user supplied data (forms, cookies, HTTP headers, etc.) to a system shell.

Vulnerable Examples

Python (Vulnerable):

python
import os
os.system(f"ping -c 4 {user_input}")

Node.js (Vulnerable):

javascript
const exec = require('child_process').exec;
exec(`ping -c 4 ${userInput}`);

PHP (Vulnerable):

php
system("ping -c 4 " . $_GET['host']);

Secure Implementation

Python (subprocess with list arguments):

python
import subprocess
import shlex
import re

def safe_ping(host):
    # Validate input
    if not re.match(r'^[a-zA-Z0-9.-]+$', host):
        raise ValueError("Invalid hostname")
    
    # Use list form (no shell interpretation)
    result = subprocess.run(
        ['ping', '-c', '4', host],
        capture_output=True,
        text=True,
        timeout=30
    )
    return result.stdout

Node.js (execFile with array arguments):

javascript
const { execFile } = require('child_process');

function safePing(host, callback) {
    // Validate input
    if (!/^[a-zA-Z0-9.-]+$/.test(host)) {
        return callback(new Error('Invalid hostname'));
    }
    
    execFile('ping', ['-c', '4', host], (error, stdout, stderr) => {
        callback(error, stdout);
    });
}

PHP (escapeshellarg):

php
$host = escapeshellarg($_GET['host']);
$output = shell_exec("ping -c 4 " . $host);

Best Practice

The best way to prevent command injection is to avoid calling system commands entirely. Use built-in language APIs instead (e.g., use a library to parse XML instead of calling a command-line tool).

๐Ÿงช Testing Verification

After implementing fixes, verify they work with these test payloads:

SQL Injection Test Payloads

Basic Tests:
' OR '1'='1 ' OR 1=1-- 1; DROP TABLE users--
Expected Result:

Query should fail or return no results

No SQL errors exposed to user

Application logs show bound parameters

Command Injection Test Payloads

Basic Tests:
; ls -la | cat /etc/passwd $(whoami)
Expected Result:

Command not executed

Input rejected or sanitized

Only expected output returned

bash
# Automated testing with SQLMap (verify fix blocks injection)
sqlmap -u "https://example.com/api/user?id=1" --batch --level=3

# If properly fixed, SQLMap should report:
# "all tested parameters do not appear to be injectable"

Common Mistakes

Blacklist Filtering

Trying to block specific keywords like "SELECT", "DROP", "UNION" is easily bypassed with encoding, case variations, or alternative syntax.

SeLeCt, %53%45%4C%45%43%54, /*!SELECT*/

Escaping Instead of Parameterization

Using escape functions like mysql_real_escape_string() or manual quote escaping is error-prone and doesn't protect against all injection vectors. Always use parameterized queries.

Parameterizing Only Some Inputs

Fixing user-facing inputs but leaving admin panels, internal APIs, or batch jobs vulnerable. ALL user-controlled data must use parameterized queries.

Using String Interpolation with ORMs

Even with ORMs, using raw queries with string interpolation reintroduces vulnerabilities.