TL;DR
The strtoupper() function in PHP doesn’t prevent SQL injection attacks when used to sanitize user input before including it in a MySQL query. Attackers can bypass this by using character encoding tricks or database-specific functions that ignore case sensitivity, allowing them to inject malicious SQL code.
Solution Guide
- Understand the Problem: The
strtoupper()function converts strings to uppercase. While it might seem like a security measure (e.g., comparing against known uppercase keywords), it’s easily bypassed because MySQL queries are often case-insensitive by default, and attackers can manipulate input to achieve their goals.- Case Insensitivity: MySQL doesn’t usually care if you use
SELECTorselect. - Character Encoding: Attackers can exploit different character encodings (e.g., UTF-8) to bypass case conversion.
- Case Insensitivity: MySQL doesn’t usually care if you use
- Identify Vulnerable Code: Look for code where user input is converted to uppercase using
strtoupper()and then directly included in a MySQL query. For example: - Bypass Techniques: Attackers can use several techniques to bypass
strtoupper():- Mixed Case Encoding: Use a combination of uppercase and lowercase characters that, when interpreted by MySQL, result in the desired case-insensitive match. For example, `SeLeCt`.
- Hexadecimal Representation: Use hexadecimal encoding to represent characters. MySQL can interpret hexadecimal representations correctly.
SELECT * FROM users WHERE username = '0x53656c656374' -- Equivalent to SELECT - Database-Specific Functions: Some databases have functions that ignore case sensitivity. For example, in MySQL:
SELECT * FROM users WHERE LOWER(username) = LOWER('$userInput')
- Prevent SQL Injection (Best Practices): The correct way to prevent SQL injection is not relying on functions like
strtoupper(). Use these methods:- Prepared Statements: Prepared statements with parameterized queries are the most effective defense.
prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute([$userInput]); ?> - Escaping User Input: If prepared statements aren’t possible, use database-specific escaping functions (e.g.,
mysqli_real_escape_string()for MySQL). - Input Validation: Validate user input to ensure it conforms to expected formats. This reduces the attack surface.
- Prepared Statements: Prepared statements with parameterized queries are the most effective defense.
- Example Attack Scenario: Consider the vulnerable code from step 2. An attacker could use a URL like this:
http://example.com/?username=SeLeCt+*+FROM+usersThis would likely bypass the
strtoupper()function and execute a malicious SQL query, potentially revealing all user data.

