Prevent SQL Injection | Database Security Best Practices
# CHAPTER 26
Database Security and SQL Injection Prevention
1. Introduction
You have built a masterpiece. Your schema is normalized, your indexes are fast, and your queries are flawless. Then, a malicious user types 10 characters into your website's login box, and your entire database is instantly deleted. This is SQL Injection (SQLi)—the oldest, most common, and most devastating cybersecurity vulnerability on the internet. In this chapter, we will learn exactly how hackers exploit SQL, and the unbreakable architectural pattern required to stop them.2. Learning Objectives
By the end of this chapter, you will be able to:- Understand the mechanics of an SQL Injection attack.
- Identify vulnerable application code.
- Implement the absolute solution: Prepared Statements.
- Understand the Principle of Least Privilege.
- Apply basic Database Security best practices.
3. The Anatomy of an SQL Injection Attack
Imagine a PHP login script. The backend takes the email the user typed into the form, and stitches it directly into an SQL string:*If the user plays nice, the final SQL string sent to the database looks like this:*
SELECT * FROM users WHERE email = 'admin@site.com'; (Perfect).
The Attack:
What if a hacker types this exact string into the email box:
' OR 1=1; --
*The PHP script blindly stitches it in. The final SQL sent to the database becomes:*
SELECT * FROM users WHERE email = '' OR 1=1; --';
Why this is catastrophic:
The database evaluates 1=1. Is 1 equal to 1? Yes. True. Because of the OR operator, the entire WHERE clause evaluates to True for *every single row in the table*. The database returns the first user in the table (which is usually the Admin). The hacker instantly bypasses the password check and logs in as the Admin!
*(Worse: They could have typed '; DROP TABLE users; -- and deleted your database!).*
4. The Cure: Prepared Statements (Parameterized Queries)
The fundamental flaw of SQL Injection is treating "User Input" as "Executable Code". The absolute, 100% mathematically guaranteed cure is using Prepared Statements.With Prepared Statements, you separate the SQL structure from the Data. You send the SQL structure to the database first, using placeholders (?). The database compiles it. *Then*, you send the user's input separately.
Why this is unbreakable:
Because the SQL structure is already compiled, when the hacker sends '; DROP TABLE users; --, the database treats it as a literal text string. It will physically search the table for a user whose legal email address is literally "; DROP TABLE users; --". It finds nothing, and the attack fails harmlessly.
5. The Principle of Least Privilege
Even with Prepared Statements, if a hacker finds another exploit, you want to limit the damage. The database user account that your PHP/Node.js web application uses to connect to MySQL should NEVER be theroot or admin user.
-
The Web App user should only have
SELECT,INSERT,UPDATE,DELETEpermissions.
-
The Web App user should never have
DROPorALTERpermissions. If they can't drop tables, a hacker who gains access to that connection cannot drop tables either!
6. Hashing Passwords
A database should never store raw passwords ('password123'). If the database is compromised, the hackers have everyone's passwords.
Application backends must use cryptographic hashing (like bcrypt or Argon2) *before* saving the password to the SQL database.
*What the database should see:*
INSERT INTO users (password_hash) VALUES ('$2y$10$abcdefghijklmnopqrstuv...');
7. Common Mistakes
-
Using String Replacement for Security: Beginners sometimes try to "sanitize" inputs by writing functions that delete the word
DROPor remove single quotes from user input. Hackers are smarter than these filters. They will encode their payloads or bypass your Regex. Never sanitize manually. ONLY use Prepared Statements.
8. Best Practices
-
Disable Remote Root Login: By default, your database server should physically reject any connection attempting to log in as
rootunless the connection originates from the exact same physical server (localhost). Never expose port 3306 or 5432 directly to the public internet without a firewall.
9. Exercises
- 1. What is the exact definition of an SQL Injection attack?
- 2. What cryptographic technique must be applied to user passwords *before* they are stored in the SQL database?
10. SQL Challenges
You are reviewing a colleague's Node.js code:db.query("DELETE FROM posts WHERE id = " + request.body.id);. Identify the vulnerability and explain conceptually how to fix it.
*(Answer: It is highly vulnerable to SQLi because of direct string concatenation. It must be refactored to use a Parameterized Query / Prepared Statement, substituting the variable with a placeholder).*
11. MCQ Quiz with Answers
What is the fundamental, foolproof defense mechanism against all forms of SQL Injection attacks?
Under the Principle of Least Privilege, what permissions should the standard Database User Account (the account used by the PHP/Node.js web server) be strictly denied?
12. Interview Questions
-
Q: Explain the mechanical step-by-step process of how a classic
' OR 1=1; --SQL Injection attack forces a vulnerable login script to authenticate an attacker.
- Q: Why is attempting to manually "sanitize" or "clean" user input considered an obsolete and dangerous architectural practice compared to utilizing Prepared Statements?