Understanding SQL injection vulnerabilities
📘 What is SQL injection vulnerability?
SQL injection vulnerabilities occur when untrusted data is sent to an interpreter (such as a database engine, command shell, or LDAP server) as part of a command or query. If the data isn’t properly validated or sanitized, attackers can manipulate the interpreter into executing unintended commands or accessing unauthorized data.
According to the OWASP organization, 94% of tested applications were found vulnerable to some form of injection !
🧪 Demonstration
Let’s shows how an injection vulnerability can occur when user input is improperly handled in a SQL query.
This example uses the database/sql
package with a SQLite driver (github.com/mattn/go-sqlite3) to simulate a vulnerable login system.
package main
import ( "database/sql" "fmt" "log" "net/http"
_ "github.com/mattn/go-sqlite3")
func main() { db, err := sql.Open("sqlite3", "./test.db") if err != nil { log.Fatal(err) } defer db.Close()
// Create a simple users table db.Exec("CREATE TABLE IF NOT EXISTS users (username TEXT, password TEXT)") db.Exec("INSERT INTO users (username, password) VALUES ('admin', 'admin123')") http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) { username := r.URL.Query().Get("username") password := r.URL.Query().Get("password")
// ❌ Vulnerable to SQL Injection query := fmt.Sprintf("SELECT * FROM users WHERE username='%s' AND password='%s'", username, password) rows, err := db.Query(query) if err != nil { http.Error(w, "Database error", http.StatusInternalServerError) return } defer rows.Close()
if rows.Next() { fmt.Fprintf(w, "Login successful!") } else { fmt.Fprintf(w, "Invalid credentials.") } })
fmt.Println("Server running at http://localhost:8080") http.ListenAndServe(":8080", nil)}
We expect that opening these URLs will attempt to log in the user :
http://localhost:8080/login?username=admin&password=wrong_password
http://localhost:8080/login?username=admin&password=admin123
💣 Exploiting the vulnerability
We can exploit this vulnerability by visiting this URL:
http://localhost:8080/login?username=admin&password=' OR '1'='1
This will bypass authentication because the SQL query becomes:
SELECT * FROM users WHERE username='admin' AND password='' OR '1'='1'
Even if the password is incorrect, the condition '1'='1'
causes the entire WHERE clause to evaluate as true, resulting in the admin user being returned.
We can imagine more destructive queries, like :
http://localhost:8080/login?username=admin&password=%27%3BDROP%20TABLE%20users%3B--
Now, we can imagine that the attacker could access sensitive data, modify or delete it, execute administrative operations (such as dropping tables or creating users), or even take control of the server in some cases !
🛡️ How to prevent injection attacks
To fix the vulnerability, we can use prepared statements with parameterized queries. It prevents injection by separating SQL logic from data.
// Define the query and use placeholders (?)stmt, err := db.Prepare("SELECT * FROM users WHERE username=? AND password=?")
if err != nil { http.Error(w, "Database error", http.StatusInternalServerError) return}
// Execute the query with user-provided values safelyrows, err := stmt.Query(username, password)
🐝 Recommendations
To mitigate injection risks, OWASP recommends:
- Prefer parameterized queries or ORM (Object Relational Mapping tools).
- Apply strict server-side validation and allow only expected formats.
- When dynamic queries are unavoidable, escape user input using interpreter-specific syntax.
- Incorporate static (SAST), dynamic (DAST), and interactive (IAST) testing into your CI/CD pipeline to catch injection flaws early.
Understanding XSS vulnerabilities
In this article, we will explore how XSS vulnerabilities work and how to prevent them
Understanding CSRF vulnerabilities
In this article, we will explore how CSRF vulnerabilities work and how to prevent them
Practice code with the "Quick Sort" algorithm
Enhance your coding skills by learning how the Quick Sort algorithm works!
The SOLID/STUPID principles
Learn what are the SOLID and STUPID principles with examples
Create a Docker Swarm playground
Let's create Docker Swarm playground on your local machine
Create an Ansible playground with Docker
Let's create an Ansible playground with Docker
HashiCorp Vault - Technological watch
Learn what is HashiCorp Vault in less than 5 minutes !
Setup a Kubernetes cluster with K3S, Traefik, CertManager and Kubernetes Dashboard
Let's setup step by step our own K3S cluster !