Bases de datos

Capa de aplicación

Aplicación

Sin importar el lenguaje que elijan, el procedimiento general de interacción con una base de datos es básicamente el mismo

Interfaz

Aplicación

Base de datos

Aplicación

¿Qué tanto podemos confiar en la información que proviene desde la interfaz?

$query = "SELECT nombre, apellido, saldo
    FROM usuario INNER JOIN cuenta
    	ON usuario.id = cuenta.usuario_id
	WHERE usuario.username = '" + $_POST['username'] + "' 
	AND password ='" + $_POST['password'] + "'";
String query =  "SELECT nombre, apellido, saldo
    FROM usuario INNER JOIN cuenta
    	ON usuario.id = cuenta.usuario_id
	WHERE usuario.username = '" + request.getParameter("username") + "'
	AND password ='" + request.getParameter("password") + "'";

PHP

Java

SELECT usuario.nombre, usuario.apellido, cuenta.saldo
FROM usuario INNER JOIN cuenta
   	ON usuario.id = cuenta.usuario_id
WHERE usuario.username = 'USERNAME' 
AND password ='PASSWORD';

MySQL

Aplicación

¿Qué tanto podemos confiar en la información que proviene desde la interfaz?

$query = "SELECT usuario.nombre, usuario.apellido, cuenta.saldo
    FROM usuario INNER JOIN cuenta
    	ON usuario.id = cuenta.usuario_id
	WHERE usuario.username = '" + $_POST['username'] + "' 
	AND usuario.password ='" + $_POST['password'] + "'";
String query =  "SELECT usuario.nombre, usuario.apellido, cuenta.saldo
    FROM usuario INNER JOIN cuenta
    	ON usuario.id = cuenta.usuario_id
	WHERE usuario.username = '" + request.getParameter("username") + "'
	AND usuario.password ='" + request.getParameter("password") + "'";

PHP

Java

SELECT usuario.nombre, usuario.apellido, cuenta.saldo
FROM usuario INNER JOIN cuenta
   	ON usuario.id = cuenta.usuario_id
WHERE usuario.username = '200239644' 
AND usuario.password ='#$$%$%&123';

MySQL

Aplicación

¿Qué tanto podemos confiar en la información que proviene desde la interfaz?

$query = "SELECT usuario.nombre, usuario.apellido, cuenta.saldo
    FROM usuario INNER JOIN cuenta
    	ON usuario.id = cuenta.usuario_id
	WHERE usuario.username = '" + $_POST['username'] + "' 
	AND usuario.password ='" + $_POST['password'] + "'";
String query =  "SELECT usuario.nombre, usuario.apellido, cuenta.saldo
    FROM usuario INNER JOIN cuenta
    	ON usuario.id = cuenta.usuario_id
	WHERE usuario.username = '" + request.getParameter("username") + "'
	AND usuario.password ='" + request.getParameter("password") + "'";

PHP

Java

SELECT usuario.nombre, usuario.apellido, cuenta.saldo
FROM usuario INNER JOIN cuenta
   	ON usuario.id = cuenta.usuario_id
WHERE usuario.username = '1' OR '1' = '1'
AND usuario.password ='1' OR '1' = '1';

MySQL

usuario:

1' or '1' = '1

password:

1' or '1' = '1

Aplicación

La consulta resultante regresa un usuario registrado porque la cláusula 1 = 1 es siempre verdadera

SELECT usuario.nombre, usuario.apellido, cuenta.saldo
FROM usuario INNER JOIN cuenta
   	ON usuario.id = cuenta.usuario_id
WHERE usuario.username = '1' OR '1' = '1'
AND usuario.password ='1' OR '1' = '1';

MySQL

A este tipo de vulnerabilidades se le conoce como inyección de SQL porque, literalmente, trata de inyectar código para hacer que una consulta se cumpla sin importar su origen

Instrucciones preparadas

Hay muchas (pero muchas) soluciones distintas para lidiar con el problema de inyección desde diversos lenguajes de programación:

  • Validación
  • Sanitización
  • Codificación
  • y un largo, largo, laaaaargo etcétera

Instrucciones preparadas

Hay muchas (pero muchas) soluciones distintas para lidiar con el problema de inyección desde diversos lenguajes de programación:

  • Validación
  • Sanitización
  • Codificación
  • y un largo, largo, laaaaargo etcétera

Pero la más conveniente está dada directamente por nuestro SGBD: las instrucciones preparadas

Instrucciones preparadas

Una instrucción preparada es una consulta parametrizada que el SGBD puede tener lista antes de ser utilizada

Instrucciones preparadas

Una instrucción preparada es una consulta parametrizada que el SGBD puede tener lista antes de ser utilizada

$query = "SELECT nombre, apellido, saldo
    FROM usuario INNER JOIN cuenta
    	ON usuario.id = cuenta.usuario_id
	WHERE usuario.username = ? 
	AND password = ?";

$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $_POST['username'], $_POST['password']);
$stmt->execute();
$result = $stmt->fetchAll();
String query =  "SELECT nombre, apellido, saldo
    FROM usuario INNER JOIN cuenta
    	ON usuario.id = cuenta.usuario_id
	WHERE usuario.username = ?
	AND password = ?";
    
PreparedStatement statement = connection.prepareStatement(query);
statement.setInt(1, request.getParameter("username")); 
statement.setInt(2, request.getParameter("password")); 
ResultSet rs = statement.executeQuery();

PHP

Java

Instrucciones preparadas

También podemos usarlas dentro de algún ciclo

$query = "INSERT INTO usuario (nombre, apellido) VALUES (?, ?)";
$stmt = $conn->prepare($query);

foreach ($usuarios as $usuario)
{
	$stmt->bind_param("ss", $usuario['nombre'], $usuario['apellido']);
	$stmt->execute();
}
String query = "INSERT INTO usuario (nombre, apellido) VALUES (?, ?)";
    
PreparedStatement statement = connection.prepareStatement(query);

for (int u: usuarios)
{
  statement.setInt(1, u->getNombre()); 
  statement.setInt(2, u->getApellido()); 
  statement.executeQuery();
}

PHP

Java

Instrucciones preparadas

También podemos usarlas dentro de una transacción

$sql = "START TRANSACTION";
$conn->query($sql);

$query = "INSERT INTO usuario (nombre, apellido) VALUES (?, ?)";
$stmt = $conn->prepare($query);

foreach ($usuarios as $usuario)
{
	$stmt->bind_param("ss", $usuario['nombre'], $usuario['apellido']);
	$stmt->execute();
}

$sql = "COMMIT";
$conn->query($sql);
String sql = "START TRANSACTION";
statement.execute(sql);

String query = "INSERT INTO usuario (nombre, apellido) VALUES (?, ?)";
    
PreparedStatement statement = connection.prepareStatement(query);

for (int u: usuarios)
{
  statement.setInt(1, u->getNombre()); 
  statement.setInt(2, u->getApellido()); 
  statement.executeQuery();
}

String sql = "COMMIT";
statement.execute(sql);

PHP

Java

Bases de datos: Capa de aplicación

By Gilberto 🦁

Bases de datos: Capa de aplicación

Capa de aplicación

  • 49