Las medidas de seguridad son inevitables al desarrollar aplicaciones web. Entre ellos, la "inyección SQL" se conoce como una amenaza grave para las bases de datos.
En este artículo, explicaremos de una manera fácil de entender cómo funciona la inyección de SQL y demostrará cómo se llevan a cabo los ataques. Además, una implementación segura utilizando Spring Boot y MyBatis, ¡ con código! Esta es una lectura obligada para los desarrolladores web, desde principiantes hasta jugadores intermedios.
¿Qué es la inyección de SQL? ¡Experimenta los peligros de los ataques a través de videos!
La inyección de SQL es un ataque que utiliza vulnerabilidades en una aplicación para lanzar operaciones fraudulentas en una base de datos.
Incluso si lo encuentras "parece un poco difícil ...", ¡podrás tener una idea aproximada de qué tipo de ataque es viendo el video corto a continuación!
📺 Mire la demostración en YouTube : puede verlo desde este enlace
El video explica cómo funciona la inyección SQL con ejemplos simples.
¡Eche un vistazo y proceda a la siguiente sección para obtener más información!
¿Qué es la inyección de SQL?
una técnica de ataque en la que un atacante inyecta un código SQL malicioso cuando una aplicación interactúa con una base de datos lo que hace que un atacante realice operaciones ilícitas.
- Adquisición no autorizada de datos : se pueden filtrar información del usuario y datos confidenciales.
- Autenticación de omisión : un atacante puede iniciar sesión sin autorización.
- DATOS DE DATOS DE DATOS : La base de datos se manipula y la confiabilidad se ve comprometida.
Cómo funciona la inyección SQL en ejemplos concretos
La función de inicio de sesión explica cómo funciona. Por ejemplo, para los siguientes parámetros, SQL se convierte así:
- Nombre de usuario:
administrador
- Contraseña:
contraseña
Seleccione Count (*)> 0 de usuarios donde username = 'admin' y contraseña = 'contraseña';
Este es un comportamiento normal, pero lo que sucede si un atacante ingresa algo como esto:
- Nombre de usuario:
'o' 1 '=' 1 ' -
- Contraseña:
cualquier valor
Esto se puede reescribir de la siguiente manera:
Seleccione Count (*)> 0 de usuarios donde userName = '' o '1' = '1' - y contraseña = 'cualquier valor';
Resultado : - y contraseña = 'cualquier valor'
se comenta por -
O '1' = '1
siempre es cierto, por lo que todos los usuarios se consideran autenticados y son posibles inicios de sesión no autorizados.
Cómo lidiar con la inyección SQL
La inyección de SQL es una amenaza grave para la seguridad de la aplicación. Sin embargo, tomar medidas apropiadas puede mitigar efectivamente este riesgo.
Esta vez, explicaremos cómo tomar medidas usando el arranque de primavera y mybatis Aprenda a crear aplicaciones seguras aprovechando estas herramientas.
1. Use una consulta parametrizada con marcadores de posición
Resumen : enlace de forma segura los parámetros utilizando marcadores de posición (#{}) en lugar de integrar la entrada del usuario directamente en las declaraciones SQL.
Razón : los marcadores de posición escapan automáticamente los valores de entrada y evitan la inyección de SQL.
A continuación se presentan los códigos que usan marcadores de posición y códigos que no se utilizan.
Las diferencias son las partes "'$ {nombre de usuario}' →#{username} '" y "' $ {contraseña} '→#{contraseña}'".
En el caso de MyBatis, puede unir los parámetros de forma segura configurándolo en
#{}
Si desea usar parámetros como está en SQL, asegúrese de usar #{}
Vulnerable
@Select ("Seleccione Count (*)> 0 de los usuarios donde username = '$ {username}' y contraseña = '$ {contraseña}'") boolean vulnerableAuthenticate (@param ("username") string username, @param ("contraseña") cadena contraseña);
seguridad
@Select ("Seleccione Count (*)> 0 de Usuarios donde username = #{username} y contraseña = #{contraseña}") boolean secureAuthenticate (@param ("username") string username, @param ("contraseña) cadena contraseña);
2. Verificación y desinfección de la entrada del usuario
Resumen : restringe los tipos y formatos que los usuarios pueden ingresar, evitando la entrada ilegal.
Razón : Eliminar cadenas peligrosas y palabras clave SQL puede reducir significativamente la tasa de éxito de su ataque.
restringir el tipo de caracteres y el formato de un parámetro, o eliminar o escapar de caracteres específicos (por ejemplo , '
, -
,; etc.
) para evitar la inyección de SQL.
if (! username.matches ("^[A-ZA-Z0-9]+$")) {arrojar nuevo IlegalArGumentException ("Entrada no válida"); }
Básicamente, es mejor considerar "1. Use una consulta parametrizada con marcadores de posición", pero si es imposible, esta solución puede reducir significativamente la tasa de éxito del ataque.
3. Evite la construcción de consultas dinámicas
Resumen : utiliza consultas parametrizadas en lugar de generar dinámicamente declaraciones SQL con operaciones de cadena.
Razón : la construcción de SQL con manipulaciones de cuerdas hace que la inyección de SQL sea más probable.
Esto es un poco diferente de las contramedidas, pero creo que es mejor comprender
que el uso de la manipulación de cadenas (+ operadores o string.format) cuando el ensamblar SQL dinámico dará como resultado un riesgo de inyección SQL.
MyBatis está diseñado de forma predeterminada para evitar el uso de operaciones de cadena para construir consultas directamente, por lo que esto no es un problema, pero tenga cuidado si está utilizando operaciones de cadena al ensamblar SQL dinámico.
En casos pasados, he visto fuentes que construyen una declaración Where utilizando la manipulación de cadenas y la establecen con $ {}.
En este caso, por supuesto, la posibilidad de inyección de SQL aumenta.
public string buildWherEclause (String UserName, String Correo electrónico) {String WhereClause = "Where 1 = 1"; if (username! = null) {whereClause + = "y username = '" + username + "'"; } if (correo electrónico! = null) {whereClause + = "y correo electrónico = '" + correo electrónico + "'"; } return WhereClause; } @Select ("Seleccionar * de los usuarios $ {WhereClause}") Lista<User> Findusers (@param ("WhereClause") cadena WhereClause);
En el caso de mybatis,<if> Puede generar consultas dinámicas utilizando esta opción, así que asegúrese de usar esto.
<select id="findUsers" resultType="User">Seleccione * de los usuarios donde 1 = 1<if test="username != null"> Y nombre de usuario = #{nombre de usuario}</if><if test="email != null"> Y correo electrónico = #{correo electrónico}</if></select>
4. Otro
Hay varias otras formas de reducir la inyección de SQL, pero es importante comprender que no es perfecto y es simplemente una mitigación.
- Establecer permisos mínimos de base de datos
- Uso de procedimientos almacenados
- Implementación de firewall de aplicaciones web (WAF)
- etc.
Implementación de ejemplo usando Spring Boot + MyBatis
Como se mencionó en YouTube, hemos incluido una implementación de ejemplo que le permite demostrar la inyección SQL.
Todo el código fuente se publica en GitHub, así que verifíquelo si lo necesita.
💾 Repositorio de GitHub : ¡verifique el código fuente en este enlace
Controlador
paquete com.youtube.security.app.security_demo.controller; import com.youtube.security.app.security_demo.repository.sqlinectionMapper; importar org.springframework.web.bind.annotation.postmapping; importar org.springframework.web.bind.annotation.requestparam; importar org.springframework.web.bind.annotation.restController; /** * Este controlador muestra cómo surgen vulnerabilidades de inyección SQL y proporciona una implementación segura utilizando * myBatis. * * La inyección SQL es un tipo de ataque que hace que las declaraciones SQL arbitrarias posibles en una base de datos inyectar un código SQL malicioso en una consulta. * * Ejemplo de implementación segura: * - Use una consulta parametrizada con marcadores de posición * -> previene la inyección SQL mediante el uso de marcadores de posición (#{}) en lugar de incrustar la entrada del usuario directamente en la consulta. * - Verifique y desinfecte la entrada del usuario * -> Aumente la seguridad limitando el tipo de carácter que el usuario puede ingresar, y eliminar y escapar de caracteres y símbolos peligrosos. * - Evite la generación dinámica de SQL con operaciones de cadena * -> usando operaciones de cadena (+ operadores y string.format) cuando ensamblar SQL dinámico aumenta el riesgo de inyección SQL. * -> Es importante ensamblar consultas de manera segura, no generarlas dinámicamente con manipulaciones de cadenas. * -> myBatis está diseñado de forma predeterminada para evitar la forma de construir consultas directamente utilizando la manipulación de la cadena. * * * Esta clase debe usarse solo para fines educativos. */ @RestController public class sqlinyectionController {private final sqlinijymapper sqlinyectionMapper; public sqlinyectionController (sqlinectionMapper sqlinyectionMapper) {this.sqlinyectionMapper = sqlinectionMapper; } /*** Ejemplo de una consulta vulnerable usando mybatis. * * @param UserName Nombre de usuario * @param contraseña contraseña * @return resultado de inicio de sesión (éxito o fail) */@PostMapping ("/login/vulnerable") public String public VulnerableLogin (@RequestParam String UserName, @RequestParam String String Password) {// Llame a MyBatis Vulnerable Query Boolean es Autenticado = = sqlinectionMapper.vulnerableAuthenticate (nombre de usuario, contraseña); ¿Returgar isAuthenticated? "Inicio de sesión de éxito (implementación vulnerable)": "Iniciar sesión fallido (implementación vulnerable)"; } /*** Ejecutar consultas parametrizadas usando mybatis. * * @param UserName Nombre de usuario * @param contraseña contraseña * @return resultado de inicio de sesión (éxito o falla) */@PostMapping ("/login/seguro") public string secureLogin (@RequestParam String UserName, @RequestParam String String Password) {// Llame a MyBATIS Secure Secure Qery ISautenticated = sqlinectionMapper.SecureAuthent (USERNACETATADE (USERNEATA (Call MyBATIS SECURI ¿Returgar isAuthenticated? "Inicio de sesión exitoso (implementación segura)": "Iniciar sesión fallido (implementación segura)"; }}
Mapabón
paquete com.youtube.security.app.security_demo.repository; importar org.apache.ibatis.annotations.mapper; importar org.apache.ibatis.annotations.param; importar org.apache.ibatis.annotations.select; @Mapper interfaz pública SqlinectionMapper { /*** Método que ejecuta consultas SQL vulnerables. * @param username * @param contraseña contraseña * @return true Si la autenticación es exitosa, falso if falla */ @select ("seleccione Count ( *)> 0 Desde los usuarios donde username = '$ {username}' y contraseña = '$ {contraseña}'") booleanAuthENTENTENTIC /*** Método para ejecutar una consulta SQL segura. * @param UserName Nombre de usuario * @param contraseña contraseña * @return true si la autenticación es exitosa, falsa si falla */ @select ("seleccione Count ( *)> 0 desde usuarios donde username = #{username} y contraseña = #{contraseña}") boolean Secureauthenticate (@param ("userame") string username, @param ("contraseña") string contraseña); }
Práctica de la inyección SQL
Tenemos herramientas para ayudarlo a practicar la inyección SQL.
Está disponible en GitHub, así que hágalo uso. (Incluso si no lo usa, puede enviar la misma solicitud y no hay problema).
💾 Repositorio de GitHub : ¡verifique el código fuente en este enlace
El siguiente video de YouTube demuestra un ataque de inyección SQL. Este contenido le permite experimentar ejemplos específicos de ataques en persona, así que eche un vistazo.
📺 Mire la demostración en YouTube : puede verlo desde este enlace
El video demuestra cómo la inyección de SQL ataca a las vulnerabilidades de aplicación de explotación. Es una demostración simple, pero debería ayudarlo a comprender el esquema del ataque.