Neuron-PHP

SqlWhereValidator
in package

SQL WHERE clause validator to prevent SQL injection attacks

SECURITY NOTE: This class does NOT provide a sanitize() method by design. Attempting to sanitize SQL input is dangerous and error-prone. Instead:

  1. Use isValid() to REJECT dangerous input (defense in depth)
  2. Use PDO prepared statements with parameter binding (primary defense)
  3. Never concatenate user input into SQL queries

Why no sanitize() method:

  • addslashes() is unsafe (doesn't handle multi-byte encodings like GBK)
  • String escaping cannot protect against all SQL injection vectors
  • Future maintainers might assume sanitize() makes input safe (it doesn't)
  • The correct solution is parameterized queries, not string manipulation

Table of Contents

Constants

DANGEROUS_PATTERNS  = [ // SQL comments '/--/', '~\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/~', // ReDoS-safe: matches balanced block comments '/#/', // SQL commands '/\b(DROP|CREATE|ALTER|TRUNCATE|DELETE|INSERT|UPDATE|REPLACE|GRANT|REVOKE)\b/i', // Stacked queries '/;\s*\w+/', // Union attacks '/\bUNION\b/i', // Subqueries (can be dangerous in WHERE clauses) '/\bSELECT\b.{0,200}?\bFROM\b/i', // ReDoS-safe: non-greedy with max length // System functions that could be exploited '/\b(SLEEP|BENCHMARK|LOAD_FILE|OUTFILE|DUMPFILE)\b/i', // Information schema access '/\b(INFORMATION_SCHEMA|MYSQL|PERFORMANCE_SCHEMA)\b/i', // Hexadecimal literals (often used in attacks) '/0x[0-9a-fA-F]+/', // CHAR function (used to obfuscate attacks) '/\bCHAR\s*\(/i', ]
Dangerous SQL patterns that could indicate SQL injection
MAX_WHERE_LENGTH  = 10000
Maximum allowed WHERE clause length to prevent ReDoS attacks Reasonable limit: most legitimate WHERE clauses are much shorter

Methods

isValid()  : bool
Validate a WHERE clause for SQL injection attempts
parseSimpleWhere()  : array<string|int, mixed>|false
Parse a simple WHERE clause into safe components Only allows basic conditions like: column = 'value', column > 123, etc.
countUnescapedQuotes()  : int
Count unescaped quotes in a string, properly handling escaped backslashes
stripStringLiterals()  : string
Strip string literals from a WHERE clause, preserving structure

Constants

DANGEROUS_PATTERNS

Dangerous SQL patterns that could indicate SQL injection

private mixed DANGEROUS_PATTERNS = [ // SQL comments '/--/', '~\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/~', // ReDoS-safe: matches balanced block comments '/#/', // SQL commands '/\b(DROP|CREATE|ALTER|TRUNCATE|DELETE|INSERT|UPDATE|REPLACE|GRANT|REVOKE)\b/i', // Stacked queries '/;\s*\w+/', // Union attacks '/\bUNION\b/i', // Subqueries (can be dangerous in WHERE clauses) '/\bSELECT\b.{0,200}?\bFROM\b/i', // ReDoS-safe: non-greedy with max length // System functions that could be exploited '/\b(SLEEP|BENCHMARK|LOAD_FILE|OUTFILE|DUMPFILE)\b/i', // Information schema access '/\b(INFORMATION_SCHEMA|MYSQL|PERFORMANCE_SCHEMA)\b/i', // Hexadecimal literals (often used in attacks) '/0x[0-9a-fA-F]+/', // CHAR function (used to obfuscate attacks) '/\bCHAR\s*\(/i', ]

MAX_WHERE_LENGTH

Maximum allowed WHERE clause length to prevent ReDoS attacks Reasonable limit: most legitimate WHERE clauses are much shorter

private mixed MAX_WHERE_LENGTH = 10000

Methods

isValid()

Validate a WHERE clause for SQL injection attempts

public static isValid(string $whereClause) : bool
Parameters
$whereClause : string

The WHERE clause to validate

Return values
bool

True if safe, false if potentially dangerous

parseSimpleWhere()

Parse a simple WHERE clause into safe components Only allows basic conditions like: column = 'value', column > 123, etc.

public static parseSimpleWhere(string $whereClause) : array<string|int, mixed>|false
Parameters
$whereClause : string
Return values
array<string|int, mixed>|false

Array of parsed conditions or false if unsafe

countUnescapedQuotes()

Count unescaped quotes in a string, properly handling escaped backslashes

private static countUnescapedQuotes(string $str, string $quoteChar) : int

Correctly handles:

  • Backslash-escaped quotes: ' or "
  • Escaped backslashes before quotes: \' or \"
  • SQL-style doubled quotes: '' or ""

Example: 'C:\' has 2 unescaped single quotes (the \ is escaped backslash, not escaped quote)

Parameters
$str : string

String to check

$quoteChar : string

Quote character to count (' or ")

Return values
int

Number of unescaped quotes

stripStringLiterals()

Strip string literals from a WHERE clause, preserving structure

private static stripStringLiterals(string $str) : string

Removes all content inside single-quoted, double-quoted, and backtick-quoted strings, properly handling escaped quotes and backslashes. This prevents false positives when checking for SQL injection patterns (e.g., "John -- Smith" won't trigger comment detection).

Parameters
$str : string

String to process

Return values
string

String with all literal contents removed


        
On this page

Search results