errorlogs.net /SQL Injection
SQLi sqlmap
SQLi Log Examples by Technique

Union-Based (most visible in logs)

# sqlmap automated union probe — note URL-encoded spaces (%20) and comment (--)
91.108.4.12 - - [10/Apr/2025:04:12:33 +0000] "GET /products.php?id=1%20UNION%20SELECT%201%2Cuser()%2C3%2C4-- HTTP/1.1" 200 4821

# Same attack with + for spaces (also common)
91.108.4.12 - - [10/Apr/2025:04:12:34 +0000] "GET /products.php?id=1+UNION+SELECT+table_name,2,3+FROM+information_schema.tables-- HTTP/1.1" 200 9240

Boolean Blind (slower, less obvious)

# True condition — returns normal page
198.51.100.9 - - [10/Apr/2025:04:15:01 +0000] "GET /item.php?id=5+AND+1=1 HTTP/1.1" 200 3120
# False condition — returns empty/error page. Different byte count = vulnerable
198.51.100.9 - - [10/Apr/2025:04:15:02 +0000] "GET /item.php?id=5+AND+1=2 HTTP/1.1" 200 312

Error-Based

# Triggers a MySQL error to leak data in the error message
203.0.113.77 - - [10/Apr/2025:05:00:12 +0000] "GET /search.php?q=test'%20AND%20extractvalue(1,concat(0x7e,version()))-- HTTP/1.1" 500 891
# 500 + this pattern = error-based SQLi confirmed if MySQL error appears in response

Time-Based Blind (hardest to spot in logs)

# SLEEP() — if vulnerable, response takes 5 seconds. Check $request_time in Nginx logs
203.0.113.77 - - [10/Apr/2025:05:01:00 +0000] "GET /api/user?id=1;SELECT+SLEEP(5)-- HTTP/1.1" 200 220 rt=5.013
# Benchmark alternative (avoids SLEEP keyword filtering)
203.0.113.77 - - [10/Apr/2025:05:01:06 +0000] "GET /api/user?id=1+AND+BENCHMARK(5000000,MD5(1))-- HTTP/1.1" 200 220 rt=4.891

Stacked Queries / Second-Order

# Attempting to inject a second SQL statement (works on some DB drivers)
198.51.100.9 - - [10/Apr/2025:05:10:00 +0000] "GET /user.php?id=1;DROP+TABLE+users-- HTTP/1.1" 500 443
Encoding Tricks — Same Attack, Different Forms

Attackers encode payloads to evade WAFs and simple string matching. All of these are the same UNION SELECT payload:

EncodingIn Log
PlainUNION SELECT 1,2,3
URL encodedUNION%20SELECT%201%2C2%2C3
+ for spacesUNION+SELECT+1,2,3
Double encodedUNION%2520SELECT%25201%252C2%252C3
Case mixinguNiOn SeLeCt 1,2,3
CommentsUN/**/ION/**/SEL/**/ECT 1,2,3
Hex0x554e494f4e2053454c454354
💡 Use -i flag
Always use grep -i (case-insensitive) when scanning for SQLi. Attackers routinely mix case to bypass naive string matching.
Detection Commands
bash
LOG=/var/log/nginx/access.log

# Comprehensive SQLi pattern scan
grep -iE "union.{0,20}select|or\s*['\"]?\s*1\s*=\s*1|--[\s+]|%27|%2527|information_schema|extractvalue|benchmark\(|sleep\([0-9]|load_file\(|into\s+outfile" $LOG

# Filter only those that got a 200 (most dangerous)
awk '$9=="200"' $LOG | grep -iE "union.*select|information_schema|extractvalue|load_file"

# Detect time-based (Nginx only — requests taking > 3s with SQL keywords)
grep -iE "sleep\(|benchmark\(" $LOG | awk -F'rt=' 'NF>1 && $2+0 > 3'

# Identify sqlmap by User-Agent
grep -i "sqlmap" $LOG | awk '{print $1}' | sort -u

# Count SQLi attempts by source IP
grep -iE "union.*select|or.1=1|sleep\(" $LOG | awk '{print $1}' | sort | uniq -c | sort -rn
🚨 If You See SQLi with 200 Responses
A 200 response to a UNION SELECT or information_schema query means your database driver processed the injected SQL and the page returned data. This is an active breach. Immediately: take the site offline, preserve logs, check the MySQL general query log for what data was accessed, rotate all DB credentials.