domingo, 7 de junio de 2009

Inyección SQL

La inyección SQL es la segunda vulnerabilidad más común en aplicaciones web, y es muy similar a XSS. Pero no solo puede suceder en aplicaciones web, si no en toda aplicación que utilice SQL dentro de sus dominios, usando cualquier lenguaje de programación. Esta vulnerabilidad es un error de una clase más general de vulnerabilidades que puede ocurrir cuando un lenguaje de programación o de script que esté incrustado dentro de otro. Las diferentes sintaxis de cada lenguaje permiten jugar con ellos, de tal forma que al introducir cierto valor a un lenguaje éste valor puede ser manipulado para ser interpretado por el lenguaje de script de una forma tal que se pueda abusar de estas sentencias. O como lo dice wikipedia: Una inyección SQL sucede cuando se inserta o "inyecta" un código SQL "invasor" dentro de otro código SQL para alterar su funcionamiento normal, y hacer que se ejecute maliciosamente el código "invasor" en la base de datos.

Esta vulnerabilidad puede ser evitada por el programador, comprobando y manipulando la cadena entrante, para poder detectar cualquier abuso en el uso de la información entrante. Lo que se puede entender a partir de esto es que este tipo de errores se generan por la falta de conocimientos del programador, por el descuido en la programación, o en las malas costumbres de programación.

Veamos como se da este proceso de ataque y mala programación en un script PHP haciendo interfaz con MySQL y utilizando un form HTML.

El primer contacto del usuario con la aplicación es la interfaz HTML y en concreto la FORM de éste. Se pueden agregar ciertas restricciones a la entrada de tal forma que pareciera segura la aplicación:



< form action=”process.php” method=”POST” >
Seleccione el color:
< select name=”color” >
< option value=”red” > rojo< /option >
< option value=”verde” > verde< /option >
< option value=”azul” > azul< /option >
< /select >
< input type=”submit” / >
< /form >


Sin embargo, sabemos que no sería suficiente con esta restricción, pues es posible ingresar directamente los valores al script process.php sin la necesidad de limitarnos a las opciones antes vistas.

process.php?color=morado

hasta este punto llega el ataque XSS, donde se introduce código mailicioso dentro de las entradas que no se suponen que puedan ser distintas, pero ahora veamos como se da esto en una entrada donde la cadena será usada en una sentencia SQL.

Supongamos el siguiente script PHP:


Si el usuario es una perosona bien intencionada introducirá su usuario y si password sin que pase nada. La sentencia SQL sería:

SELECT count(*)
FROM users
WHERE username = ‘juan’
AND password=’eselmejor’”;

y Juan accesará a su cuenta sin mayor problema.

Pero el pasado script es vulnerable, pues no comprueba la entrada que llega del método POST. Supongamos que el atacante sabe que -- es el comando SQL para comentario, entonces, todo lo que se introduzca después de los dos guiones no será reconocido por el SQL y se evita automáticamente la comprobación del password, dando acceso total el invasor. Con la siguiente entrada de usuario será:

Juan’--

Se ejecutará la siguiente sentncia:

SELECT count(*)
FROM users
WHERE username = ‘juan’--‘
AND password=’eselmejor’”;

Pero como AND password=… es un comentario no será tomado en cuenta será ejecutado:

SELECT count(*)
FROM users
WHERE username = ‘juan’

Entrando a la cuenta de Juan sin permiso y evitando la comprobación de password.

Veamos que otros posibles abusos pueden ser cometidos con Inyección SQL. Hace búsqueda de fuerza bruta del password del un usuario con una cierta dirección de correo electrónico:

SELECT email, passwd, login_id, full_name
FROM members
WHERE email = 'bob@example.com' AND passwd = 'hello123';


Elimina una tabla de la base de datos:

SELECT email, passwd, login_id, full_name
FROM members
WHERE email = 'x'; DROP TABLE members; --'; -- Boom!

Crea una nueva cuenta papra poder acceder a la base de datos in mayor problema:

SELECT email, passwd, login_id, full_name
FROM members
WHERE email = 'x';
INSERT INTO members ('email','passwd','login_id','full_name')
VALUES ('steve@unixwiz.net','hello','steve','Steve Friedl');--';

Y así se podría continuar hasta que la imaginación lo permita. Pero ahora surge la preunta: ¿Cómo se debió haber programado el script PHP desde el principio para poder evitar estos ataques?

Se debe comprobar la cadena entrante de la siguiente forma:

prepare(‘ SELECT count(*)
FROM users
WHERE username =:username’
AND password=:hash’);

$sql->bindParam( ‘:username’,
$clean[‘username’],
PDO_PARAM_STRING,
32);

$sql->bindParam( ‘:hash’,
$hash($_POST[‘password’]),
PDO_PARAM_STRING,
32);
.......

?>


Referencia:

Rasmus Lerdorf, Kevin Tatroe & Meter MacIntyre. Programming PHP, Segunda edición abril 2006, Estados Unidos ed.: O’Reilly Media.

http://unixwiz.net/techtips/sql-injection.html

http://es.wikipedia.org/wiki/Inyecci%C3%B3n_SQL

No hay comentarios:

Publicar un comentario