|
| 1 | +# SQL Injection Vulnerability Analysis |
| 2 | +## Lesson 01 - Demo 02: Vulnerable API |
| 3 | + |
| 4 | +### Executive Summary |
| 5 | +The Express API in `demo-02-sql-injection/vulnerable/api.js` contains **8 critical SQL injection vulnerabilities** (OWASP A03:2021, CWE-89) that allow attackers to bypass authentication, exfiltrate data, and modify/delete records. |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Critical Vulnerabilities |
| 10 | + |
| 11 | +### Vulnerability 1: GET Parameter Injection |
| 12 | +**Location:** `/user/:id` endpoint (line 58) |
| 13 | + |
| 14 | +**Vulnerable Code:** |
| 15 | +```javascript |
| 16 | +const query = `SELECT * FROM users WHERE id = ${userId}`; |
| 17 | +``` |
| 18 | + |
| 19 | +**Attack Vectors:** |
| 20 | +- `/user/1 OR 1=1` → Returns all users |
| 21 | +- `/user/1 UNION SELECT username, password FROM users--` → Data exfiltration |
| 22 | + |
| 23 | +--- |
| 24 | + |
| 25 | +### Vulnerability 2: Authentication Bypass |
| 26 | +**Location:** `/login` endpoint (line 75) |
| 27 | + |
| 28 | +**Vulnerable Code:** |
| 29 | +```javascript |
| 30 | +const query = "SELECT * FROM users WHERE username = '" + username + |
| 31 | + "' AND password = '" + password + "'"; |
| 32 | +``` |
| 33 | + |
| 34 | +**Attack Vectors:** |
| 35 | +- `username: "admin'--"` → Bypasses password check |
| 36 | +- `username: "' OR '1'='1"` → Returns all users |
| 37 | + |
| 38 | +--- |
| 39 | + |
| 40 | +### Vulnerability 3: Search Function Injection |
| 41 | +**Location:** `/search` endpoint (line 118) |
| 42 | + |
| 43 | +**Vulnerable Code:** |
| 44 | +```javascript |
| 45 | +const query = `SELECT * FROM products |
| 46 | + WHERE name LIKE '%${searchTerm}%' |
| 47 | + AND category = '${category}'`; |
| 48 | +``` |
| 49 | + |
| 50 | +**Attack Vectors:** |
| 51 | +- `q=' UNION SELECT table_name, column_name, 3, 4 FROM information_schema.columns--` |
| 52 | +- `q=' OR 1=1--` |
| 53 | + |
| 54 | +--- |
| 55 | + |
| 56 | +### Vulnerability 4: ORDER BY Clause Injection |
| 57 | +**Location:** `/products` endpoint (line 143) |
| 58 | + |
| 59 | +**Vulnerable Code:** |
| 60 | +```javascript |
| 61 | +const query = `SELECT * FROM products ORDER BY ${sortBy} ${order}`; |
| 62 | +``` |
| 63 | + |
| 64 | +**Attack Vectors:** |
| 65 | +- `sort=id; DROP TABLE users;--` → Stacked queries |
| 66 | +- `sort=(SELECT password FROM users WHERE username='admin')` |
| 67 | + |
| 68 | +--- |
| 69 | + |
| 70 | +### Vulnerability 5: INSERT Statement Injection |
| 71 | +**Location:** `/register` endpoint (line 167) |
| 72 | + |
| 73 | +**Vulnerable Code:** |
| 74 | +```javascript |
| 75 | +const query = `INSERT INTO users (username, email, password, role) |
| 76 | + VALUES ('${username}', '${email}', '${password}', 'user')`; |
| 77 | +``` |
| 78 | + |
| 79 | +**Attack Vector:** |
| 80 | +- `email: "test@test.com', 'admin'); DROP TABLE users;--"` |
| 81 | + |
| 82 | +--- |
| 83 | + |
| 84 | +### Vulnerability 6: UPDATE Statement Injection |
| 85 | +**Location:** `/user/:id` PUT endpoint (line 194) |
| 86 | + |
| 87 | +**Vulnerable Code:** |
| 88 | +```javascript |
| 89 | +const query = `UPDATE users |
| 90 | + SET email = '${email}', display_name = '${displayName}' |
| 91 | + WHERE id = ${userId}`; |
| 92 | +``` |
| 93 | + |
| 94 | +**Attack Vector:** |
| 95 | +- Privilege escalation by injecting role updates |
| 96 | + |
| 97 | +--- |
| 98 | + |
| 99 | +### Vulnerability 7: DELETE Statement Injection |
| 100 | +**Location:** `/product/:id` endpoint (line 217) |
| 101 | + |
| 102 | +**Vulnerable Code:** |
| 103 | +```javascript |
| 104 | +const query = `DELETE FROM products WHERE id = ${productId}`; |
| 105 | +``` |
| 106 | + |
| 107 | +**Attack Vector:** |
| 108 | +- `id=1 OR 1=1` → Deletes all records |
| 109 | + |
| 110 | +--- |
| 111 | + |
| 112 | +### Vulnerability 8: Blind SQL Injection |
| 113 | +**Location:** `/check-user` endpoint (line 241) |
| 114 | + |
| 115 | +**Vulnerable Code:** |
| 116 | +```javascript |
| 117 | +const query = `SELECT COUNT(*) as count FROM users WHERE username = '${username}'`; |
| 118 | +// Different responses based on result |
| 119 | +if (results[0].count > 0) { |
| 120 | + res.json({ exists: true, message: 'Username taken' }); |
| 121 | +} |
| 122 | +``` |
| 123 | + |
| 124 | +**Attack Vector:** |
| 125 | +- `username: "admin' AND SUBSTRING(password,1,1)='a'--"` |
| 126 | +- Attacker extracts data character-by-character via response timing |
| 127 | + |
| 128 | +--- |
| 129 | + |
| 130 | +## Secure Alternative: Parameterized Queries |
| 131 | + |
| 132 | +All vulnerabilities are fixed by using **parameterized queries** with placeholders: |
| 133 | + |
| 134 | +```javascript |
| 135 | +// SECURE PATTERN |
| 136 | +app.get('/user/:id', (req, res) => { |
| 137 | + const userId = req.params.id; |
| 138 | + |
| 139 | + // Use ? placeholders and pass values separately |
| 140 | + const query = 'SELECT * FROM users WHERE id = ?'; |
| 141 | + |
| 142 | + db.query(query, [userId], (err, results) => { |
| 143 | + if (err) { |
| 144 | + console.error('Query error:', err); |
| 145 | + return res.status(500).json({ error: err.message }); |
| 146 | + } |
| 147 | + res.json(results); |
| 148 | + }); |
| 149 | +}); |
| 150 | +``` |
| 151 | + |
| 152 | +### Key Benefits |
| 153 | +- ✅ SQL structure is locked and cannot be altered by user input |
| 154 | +- ✅ Database driver automatically escapes values |
| 155 | +- ✅ Works for all SQL statement types (SELECT, INSERT, UPDATE, DELETE) |
| 156 | + |
| 157 | +### Fix Template |
| 158 | +Replace all endpoints following this pattern: |
| 159 | + |
| 160 | +```javascript |
| 161 | +// Before (VULNERABLE) |
| 162 | +const query = `SELECT * FROM users WHERE id = ${userId}`; |
| 163 | +db.query(query, callback); |
| 164 | + |
| 165 | +// After (SECURE) |
| 166 | +const query = 'SELECT * FROM users WHERE id = ?'; |
| 167 | +db.query(query, [userId], callback); |
| 168 | +``` |
| 169 | + |
| 170 | +--- |
| 171 | + |
| 172 | +## Recommendations |
| 173 | +1. **Immediate:** Replace all dynamic queries with parameterized queries |
| 174 | +2. **Input Validation:** Validate type and format (e.g., IDs should be integers) |
| 175 | +3. **Least Privilege:** Database user should have minimal required permissions |
| 176 | +4. **WAF:** Deploy Web Application Firewall to detect injection attempts |
| 177 | +5. **Testing:** Run SAST tools (Semgrep, SonarQube) in CI/CD pipeline |
| 178 | +6. **Education:** Train developers on secure coding practices |
| 179 | + |
| 180 | +--- |
| 181 | + |
| 182 | +## References |
| 183 | +- OWASP SQL Injection: https://owasp.org/www-community/attacks/SQL_Injection |
| 184 | +- CWE-89: https://cwe.mitre.org/data/definitions/89.html |
| 185 | +- mysql2 Documentation: https://github.com/sidorares/node-mysql2 |
0 commit comments