Seguridad en Web: Inyección SQL y XSS

En web, no importa el lenguaje, hay dos cosas que son el puntapié inicial a un “hackeo” de sitio: Inyección SQL y Cross-site Scripting (XSS).

Parte de la seguridad de un sitio pasa por la seguridad del propio servidor, pero un servidor es tan fuerte como el código que aloja también.

Inyección SQL

La inyección SQL es una vulnerabilidad común en lo que es web. Es, básicamente, inyectar código malicioso (SQL por supuesto) en la base de datos de un sitio y forzar a la base de datos a ejecutar las consultas. Las consecuencias de algo así pueden ser muchas, desde robar información privada hasta destruir la base de datos por completo.

Para evitar esto, en PHP podemos escapar las consultas usando PDO, ejemplo:

$stmt = $pdo->prepare('SELECT * FROM usuarios WHERE username = :username');
$stmt->execute(['username' => $username]);
$result = $stmt->fetch();

La función “prepare” de PDO se utiliza para preparar una sentencia SQL pasando parámetros antes de ejecutarla.

La preparación de la consulta con prepare se realiza en dos etapas:

Una vez que todo pasó “ok”, la sentencia se ejecuta en la tabla correspondiente (función execute).

También se recomienda escapar caracteres especiales usando mysql_real_escape_string o PDO::quote, con cualquiera de los dos se “entre comilla” (o escapa) un string (que es la consulta en sí) antes de ejecutarla:

$username = mysqli_real_escape_string($conn, $username);
$password = mysqli_real_escape_string($conn, $password);

$sql = "SELECT * FROM usuarios WHERE username='$username' AND password='$password'";
$result = mysqli_query($conn, $sql);

Otra cosa que se recomienda es limitar los privilegios del usuario mysql para ejecutar solo lo que necesite, pero este último punto es casi ficticio en web, generalmente hay 1 solo usuario que tiene las 4 operaciones (SELECT, INSERT, UPDATE y DELETE), de otra forma nuestros scripts no funcionan.

Bien, por supuesto, WordPress ya viene preparado para todo esto, pero siempre hay que tener en cuenta que cualquier plugin o desarrollo propio puede llevar un hueco de seguridad. En el caso de los plugins de terceros, es mejor no instalar si no estamos seguros que, valga la redundancia, sea seguro el código. Pero en el caso del código propio podemos tomar algunas medidas como las veíamos recién en php puro y duro.

WPDB Prepare

En WordPress con la clase WPDB tenemos el método “prepare”, este método recibe 2 parámetros, la sentencia a que ejecutar y los argumentos, ej:

global $wpdb;
$username = $_POST['username'];
$password = $_POST['password'];

$query = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}users WHERE user_login = %s AND user_pass = %s", $username, $password);
$results = $wpdb->get_results($query);

Si miramos detenidamente, no hay mucha diferencia con PDO, se prepara la sentencia y luego se ejecuta con get_results.

Acá lo interesante es cómo pasar los parametros al preparar, podemos ver que usa:

user_login = %s

Bien, esta “%s” tiene un sentido, son “placeholders” que utilizan una sintaxis como la de la función sprintf de php. Hay 4 “placeholders” o marcadores de posición en criollo aceptados en “prepare”:

Es decir, necesitamos que un dato de la consulta se compare con un número, usamos “%d”:

user_id = %d

Necesitamos comparar con una cadena:

user_email = %s

Necesitamos comparar con un flotante o decimal:

product_price = %f

Necesitamos comparar con un tabla o nombre de campo:

table_name = %i

Cabe recordar que para WordPress también tenemos funciones como los “nonces”, de los que vamos a hablar en otra oportunidad, pero mientras tanto con estos pequeños tips, tanto en PHP como en WordPress en sí, tenemos una capa de seguridad bastante efectiva al momento de crear un script o un plugin propio.

Contacto

Si necesitás, podemos charlar sobre tu proyecto. No te olvides de incluir todos los detalles posibles para aprovechar al máximo nuestra primera conversación.

Teléfono:

+54 9 3456 50 82 44