Improper Neutralization of Special Elements used in an SQL Command
User input is concatenated directly into SQL queries, allowing attackers to modify the query logic and access or manipulate data. This is one of the oldest and most dangerous vulnerability classes, responsible for some of the largest data breaches in history.
Cómo corregir esta vulnerabilidad
Estrategias de prevención para SQL Injection basadas en 7 reglas de detección de Shoulder.
Use parameterized queries with $1 (PostgreSQL) or ? (MySQL/SQLite) placeholders
func getUser(w http.ResponseWriter, r *http.Request) { userID := r.URL.Query().Get("id") - query := "SELECT * FROM users WHERE id = " + userID - rows, err := db.Query(query) + rows, err := db.Query("SELECT * FROM users WHERE id = $1", userID) // ... }
Use parameterized queries with placeholder syntax
- const query = `SELECT * FROM users WHERE id = '${req.params.id}'`; - await db.query(query); + const query = 'SELECT * FROM users WHERE id = $1'; + await db.query(query, [req.params.id]);
Use Prisma.sql tagged template for parameterized raw queries instead of regular template literals
- import { PrismaClient } from '@prisma/client'; - const prisma = new PrismaClient(); - - app.get('/api/users/search', async (req, res) => { - const { name } = req.query; - const users = await prisma.$queryRaw` - SELECT * FROM "User" WHERE name LIKE '%${name}%' - `; - res.json(users); - }); - // Attacker sends: name=' OR 1=1 -- + import { PrismaClient, Prisma } from '@prisma/client'; + const prisma = new PrismaClient(); + + app.get('/api/users/search', async (req, res) => { + const { name } = req.query; + const users = await prisma.$queryRaw( + Prisma.sql`SELECT * FROM "User" WHERE name LIKE ${`%${name}%`}` + ); + res.json(users); + });
Use parameterized queries with positional (?) or named (:param) placeholders instead of string interpolation
import { getManager } from 'typeorm'; app.get('/api/users/search', async (req, res) => { const { name, role } = req.query; const manager = getManager(); const users = await manager.query( - `SELECT * FROM users WHERE name = '${name}' AND role = '${role}'` - ); - res.json(users); - }); - // Attacker sends: name=' OR '1'='1' -- + 'SELECT * FROM users WHERE name = $1 AND role = $2', + [name, role] + ); + res.json(users); + });
Use parameterized GraphQL queries with variables instead of string formatting
from flask import request import graphene @app.route('/graphql', methods=['POST']) def graphql_endpoint(): - user_id = request.json.get('id') - query = f'{{ user(id: "{user_id}") {{ name email }} }}' - result = schema.execute(query) + query = request.json.get('query') + variables = request.json.get('variables', {}) + result = schema.execute(query, variables=variables) return jsonify(result.data)
Encuentra vulnerabilidades en tu código
Usa Shoulder para escanear tu código en busca de patrones SQL Injection. 7 reglas.
# Scan with Shoulder CLI npx @shoulderdev/cli trust --cwe=89 # Or scan entire project npx @shoulderdev/cli trust .
Reglas de Detección (7)
Qué buscar en las revisiones de código
Estos patrones indican vulnerabilidades potenciales de SQL Injection. Búscalos durante las revisiones de código y auditorías de seguridad.
Patrones de revisión manual
Al revisar código manualmente, busca estos patrones peligrosos.
query = + concatenación de cadenasexecute(f"... or execute("..." +raw_query, rawQuery, executeRaw${ or #{ dentro de cadenas SQLCómo piensan los expertos en seguridad
El modelo mental que usan los profesionales de seguridad al revisar esta vulnerabilidad.
Mapea los puntos de entrada
Parámetros de URL, cuerpos POST, encabezados, cookies, subidas de archivos.
Rastrea el flujo de datos
Sigue la entrada a través del código. ¿Se sanea?
Identifica los sumideros
Where queries are executed: execute(), query()
Verifica los límites de confianza
Vigila los datos almacenados que se usan en consultas.
Escanea tu base de código para SQL Injection
Shoulder CLI encuentra patrones vulnerables en toda tu base de código.