A beginner-friendly walkthrough for identifying and fixing SQL injection vulnerabilities in your own web applications.
A beginner-friendly walkthrough for identifying and fixing SQL injection vulnerabilities in your own web applications.
SQL Injection (SQLi) remains one of the most common and dangerous web application vulnerabilities, even decades after it was first identified. It occurs when user-supplied input is inserted into a database query without proper sanitization, allowing an attacker to manipulate the query itself.
This article walks through a responsible, hands-on approach to testing your own website or application for SQL injection — along with how to fix what you find.
Disclaimer: Only test applications you own or have explicit written authorization to test. Unauthorized testing of third-party systems is illegal in most jurisdictions under laws.
SQL injection happens when an application builds a database query by directly combining user input with SQL code, rather than treating that input as pure data. For example, a vulnerable login query might look like this:
SELECT * FROM users WHERE username = '$username' AND password = '$password';
If $username is set to ' OR '1'='1, the resulting query becomes:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '';
Since '1'='1' is always true, this can bypass authentication entirely.
Before testing anything, make sure you:
Identify every point where user input could reach a database query:
?id=5, ?category=books)Create a simple checklist or spreadsheet of these entry points before testing — it keeps the process organized and repeatable.
Try entering the following payloads into input fields and URL parameters, one at a time, observing how the application responds:
'
"
' OR '1'='1
' OR '1'='1' --
' OR '1'='1' #
"; DROP TABLE users; --
1' AND SLEEP(5) --
What to look for:
| Observation | Possible Meaning |
|---|---|
| Database error message appears | Input is reaching the SQL layer unsanitized |
| Login succeeds with no valid credentials | Classic authentication bypass via injection |
Page takes several seconds longer to load after a SLEEP() payload | Blind SQL injection (time-based) |
| Page content changes based on true/false conditions | Blind SQL injection (boolean-based) |
Manual testing is useful for understanding the vulnerability, but automated tools scale the process and catch cases manual testing might miss.
A widely used, open-source tool purpose-built for detecting and exploiting SQL injection:
sqlmap -u "https://yourstagingsite.com/page?id=5" --batch --dbs
This tests the id parameter and, if injectable, attempts to list available databases. Use the --risk and --level flags cautiously — higher values send more aggressive payloads that could affect application stability.
Both tools can crawl your site and automatically flag parameters that appear injectable, with a more visual, beginner-friendly interface than sqlmap. OWASP ZAP is free and open-source, making it a good starting point.
Pay particular attention to:
?sort=name)This is the primary, most effective defense. Instead of:
query = "SELECT * FROM users WHERE username = '" + username + "'"
Use:
cursor.execute("SELECT * FROM users WHERE username = %s", (username,))
Parameterized queries ensure user input is always treated as data, never as executable SQL.
Your application's database account should only have the permissions it actually needs. A web app that only reads and writes rows shouldn't have DROP or ALTER privileges.
Frameworks like SQLAlchemy (Python), Sequelize (Node.js), or Eloquent (PHP/Laravel) parameterize queries by default, reducing the chance of accidental raw concatenation.
Input validation (expected data types, lengths, formats) is a good defense-in-depth measure, but it should never be the only protection — it supplements parameterized queries, not replaces them.
Detailed database errors can leak schema information to attackers. Use generic error messages in production and log details server-side instead.
After applying fixes:
SQL injection is preventable, well-understood, and still one of the most common vulnerabilities found in real-world applications — largely because it's easy to introduce accidentally through string concatenation. A regular habit of mapping input points, testing them, and defaulting to parameterized queries closes off the vast majority of risk.
If you're building a portfolio around this kind of work, consider publishing your testing methodology, the vulnerabilities found (in a sanitized, non-sensitive way), and the fixes applied — this demonstrates both technical skill and responsible practice.
Written as part of an ongoing series on practical, hands-on cybersecurity testing.
No comments yet. Start the conversation below.