forked from mmistakes/minimal-mistakes
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Añadido el post relativo a la SQLi, primera parte
- Loading branch information
Showing
2 changed files
with
156 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
--- | ||
layout: single | ||
title: "SQL Injection (parte 1)" | ||
categories: hacking | ||
header: | ||
image: /assets/images/hacking/sqli.jpg | ||
--- | ||
|
||
# Concepto | ||
|
||
Después del post de las LFI creo que la siguiente vulnerabilidad básica que hay que conocer en el mundo del pentesting web es la inyeccion de SQL (SQL Injection para los angloparlantes), esta es una vulnerabilidad web que permite a un atacante modificar las consultas que la aplicación web realiza a la base de datos para obtener información no autorizada o saltarse ciertos controles de acceso. En algunos casos este tipo de vulnerabilidades puede comprometer la infraestructura y el funcionamiento de este servicio web. | ||
|
||
A la hora de probar en pentesting los cheatsheets pueden sernos de gran ayuda por el distintio tipo de inyecciones que existen aunque en este artículo solo se tocarán ejemplos básicos además de posibles defensas y consecuencias. | ||
|
||
# Donde se encuentran | ||
|
||
Se pueden buscar usando cierta semántica especial en las distintas entradas de datos que intuyamos que hacen consultas a una base de datos, como podría ser un inicio de sesión o alguna consulta de que impliqué datos guardados en masa como un stock de artículos. Esta se puede comprobar generalmente añadiendo: | ||
|
||
- Introduciendo `'` esperando algún error o salida anómala. | ||
- Introduciendo alguna condición lógica como `OR 1=1` y mirando la salida de la aplicación. | ||
- Probando payloads específicamente diseñados para este tipo de ataques. | ||
|
||
# Inyección tipo WHERE clause | ||
|
||
Existen múltiples tipos de inyecciones, en este artículo se expondrá la más simple, la basada en una cláusula `WHERE`. Estas suelen tener la siguiente forma: | ||
|
||
```SQL | ||
"SELECT * FROM table WHERE column1='" + parametro1 + " AND column2='" + parametro2 + "'..." | ||
``` | ||
|
||
En esta se podría omitir el número de comprobaciones que queramos ya que podemos añadir distintos tipos de comentarios (en línea o en bloque) evitando las comprobaciones que no | ||
nos convengan como atacantes y generando una consulta con nuevas condiciones que validasen cualquier campo con la exporesión `' OR 1=1 -- -` que es la más típica usada en estos casos. | ||
|
||
## Ejemplo vulnerable básico inicio de sesión | ||
|
||
Si nos imaginamos como con una consulta SQL de la manera más básica podría autenticar un usuario, podríamos imaginarnoslo de esta forma: | ||
|
||
```SQL | ||
SELECT * | ||
FROM users | ||
WHERE email = '$mail' | ||
AND password = '$pass' LIMIT 1 | ||
``` | ||
Esto funcionaría principalmente que busca en la tabla de usuarios un usuario donde coincidan un mail con su contraseña pero si en este caso existe un usuario mal intencionado y | ||
en los campos de inicio de sesión introdujese lo siguiente: | ||
|
||
- $mail: [email protected] | ||
- $pass: ' or 1=1-- | ||
|
||
Este ejemplo de entrada nos dejaría la comprobación de la contraseña como `pass = '' OR 1=1 --' LIMIT 1`, esto haría que nos registraramos con ese usuario admin ya que la condición de 1=1 es correcta por lo que `<condición> or <condición>` da como verdadera la parte de la comprobación de la contraseña y el resto se ignora porque se queda como comentario, por lo que la consulta finalmente está formada correctamente. | ||
|
||
# Riesgos | ||
|
||
- **Acceso no autorizado a datos sensibles**: Un atacante puede obtener acceso a datos confidenciales almacenados en la base de datos, como contraseñas, información personal, o datos financieros. | ||
|
||
- **Modificación de datos**: Los atacantes pueden modificar, eliminar o insertar datos maliciosos en la base de datos, lo que puede llevar a la corrupción de datos o cambios no autorizados en la información. | ||
|
||
- **Ataques de fuerza bruta**: Los atacantes pueden utilizar la inyección SQL para obtener información que les ayude a llevar a cabo ataques de fuerza bruta en otros sistemas, como contraseñas de usuario o credenciales. | ||
|
||
- **Ejecución de comandos del sistema**: Una vulnerabilidad SQLi puede permitir a los atacantes ejecutar comandos del sistema en el servidor de la aplicación, lo que puede llevar a la toma de control completa del sistema. | ||
|
||
- **Ataques de denegación de servicio (DoS)**: Los atacantes pueden aprovechar las vulnerabilidades SQLi para realizar ataques de denegación de servicio, abrumando la base de datos y la aplicación con solicitudes maliciosas. | ||
|
||
- **Divulgación de información interna**: Los atacantes pueden utilizar la inyección SQL para obtener información interna de la aplicación, como la estructura de la base de datos o detalles técnicos, que podrían facilitar futuros ataques. | ||
|
||
- **Riesgo de infección por malware**: Los atacantes pueden inyectar código malicioso en la base de datos a través de SQLi, lo que puede propagar malware a través de la aplicación o a los usuarios finales. | ||
|
||
- **Vulnerabilidades persistentes**: Si una vulnerabilidad SQLi no se corrige, los riesgos asociados pueden persistir durante un largo período, permitiendo que los atacantes continúen explotando la vulnerabilidad. | ||
|
||
# Protecciones | ||
|
||
## Usando sentencias preparadas | ||
|
||
Como la mayoría de las veces las sentencias SQL son escritas en otro lenguaje de programación y se conectan a la BD usando un driver. | ||
Una buena práctica es introducir dichos parámetros en la sentencia con métodos que nos proporcione el driver, así el driver le pasará estos parámetros a la BD por separado. | ||
|
||
### Ejemplo en Java | ||
|
||
**Seguro:** | ||
|
||
```java | ||
// Connect to the database. | ||
Connection conn = DriverManager.getConnection(URL, USER, PASS); | ||
|
||
// Construct the SQL statement we want to run, specifying the parameter. | ||
String sql = "SELECT * FROM users WHERE email = ?"; | ||
|
||
// Generate a prepared statement with the placeholder parameter. | ||
PreparedStatement stmt = conn.prepareStatement(sql); | ||
|
||
// Bind email value into the statement at parameter index 1. | ||
stmt.setString(1, email); | ||
|
||
// Run the query... | ||
ResultSet results = stmt.executeQuery(sql); | ||
|
||
while (results.next()) | ||
{ | ||
// ...do something with the data returned. | ||
} | ||
``` | ||
|
||
**Inseguro** | ||
|
||
```java | ||
|
||
// The user we want to find. | ||
String email = "[email protected]"; | ||
|
||
// Connect to the database. | ||
Connection conn = DriverManager.getConnection(URL, USER, PASS); | ||
Statement stmt = conn.createStatement(); | ||
|
||
// Bad, bad news! Don't construct the query with string concatenation. | ||
String sql = "SELECT * FROM users WHERE email = '" + email + "'"; | ||
|
||
// I have a bad feeling about this... | ||
ResultSet results = stmt.executeQuery(sql); | ||
|
||
while (results.next()) { | ||
// ...oh look, we got hacked. | ||
} | ||
``` | ||
|
||
La diferencia es que el primero le pasa el parámetro con el método *setString* por lo que es pasado a la BD aparte y el segundo podría introducirse la sentencia [[SQL]] que se quisiera. | ||
|
||
## Saltarse caracteres | ||
|
||
Esta es menos eficaz que la anterior. Trata de saltar caracteres como *'* o *"*, ya que son los típicos para indicar el fin del un string. | ||
La mayoría de lenguajes tienen funciones estándar para hacer esto. Aun así esto tiene un par de incovenientes: | ||
- Hay que tener mucho ciudado para saltar estos caracteres en cualquier sentencia [[SQL]] de la BD. | ||
- No todas las inyecciones abusan de esa vulnerabilidad. Por ejemplo si espera un tipo de dato entero, las comas ya no sirven para protegernos. | ||
|
||
## Comprobando los inputs | ||
|
||
Comprobar si el correo cuadra con nuestra expresión regular de lo que debería ser un correo, si un dato que es un número no contiene carácteres no numéricos o rechazar espacios o intros son buenas prácticas a la hora de comprobar el input que nos está dando el usuario. No nos podemos confiar con que el usuario es bueno perse, hay que comprobar que los datos que nos está pasando no son maliciosos. | ||
|
||
Hacer esto en el lado del cliente (javascript) suele estar bien para darle al cliente un feedback inmediato, pero no es una buena defensa contra atacantes buenos ya que puede que no estén usando ni navegadores para hacer las peticiones, solo usando scripts y se puedan saltar esa verificación de los inputs. | ||
|
||
|
||
# Referencias | ||
|
||
- https://www.hacksplaining.com/exercises/sql-injection | ||
|
||
- https://www.youtube.com/watch?v=C-FiImhUviM | ||
|
||
## Cheatsheets | ||
|
||
- https://www.invicti.com/blog/web-security/sql-injection-cheat-sheet/ | ||
|
||
- https://www.w3schools.com/sql/sql_union.asp | ||
|
||
- https://pentestmonkey.net/category/cheat-sheet/sql-injection | ||
|
||
- https://portswigger.net/web-security/sql-injection/cheat-sheet | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.