Sigue a Genbetadev

Evita los ataques por inyección SQL

Los ataques informáticos son nuestro pan de cada día, y entre ellos destaca últimamente los ataques de inyección de SQL, por este motivo tenemos que prevenirnos al máximo de estos ataques que cada vez se está extendiendo más su uso por la facilidad que tiene de ponerlo en marcha cualquier persona aunque no tenga experiencia en SQL, simplemente sabiendo la cadena de texto adecuada (que puede conseguir en algún foro de esta temática).

En otro artículo comenté el aumento de ataques de este tipo y lo costoso que era oponerse a los ciberataques, además de poner un ejemplo funcional de como hacer una inyección SQL y ahora os voy a explicar que medidas básicas podemos tomar para evitar estos ataques.

Como evitar estos ataques

El principal problema de estos ataques es que si dejamos que el usuario del programa introduzca libremente caracteres sin control ninguno (mediante formularios, por ejemplo) puede llegar a aprovecharse de las comillas (simples y dobles con las que declaramos cadenas de texto o strings).

Os voy a poner un pequeño ejemplo de una consulta SQL a la que le mandamos dos parámetros (independientemente del lenguaje, ya que cualquier lenguaje que use bases de datos SQL podría ser victima de estos ataques), que mediante el lenguaje que elijamos escribirá tal cual le mandemos los parámetros.

#El usuario y la contraseña que mandamos son "Error", y se haría esta consulta:
SELECT * FROM `Usuarios` WHERE `user`='Error' AND `pass`='Error'
#Y en este ejemplo veremos el resultado de la inyección del SQL
SELECT * FROM `Usuarios` WHERE `user`='Error' AND `pass`='' UNION SELECT * FROM `Usuarios` WHERE `id` = '1'

Por lo tanto la solución genérica sería evitar que se pudieran introducir caracteres especiales (como comillas) sin haberlas transformado antes (por ejemplo, una comilla doble: " debería de transformarse en \" que así interpretará como texto la comilla y no como el carácter que cierra o abre el una texto en la consulta, pero según el lenguaje se puede implementar de distintas formas y algunas son automáticas y más optimizadas.

PHP

En PHP tenemos varias formas de hacerlo, entre ellas para bases de datos MySQL tenemos la función mysql_real_escape_string, que añadiremos en las variables que introducimos en la consulta.

$respuesta=mysql_query("SELECT * FROM `Usuarios` WHERE `user`='".mysql_real_escape_string($name)."' AND `pass`='".mysql_real_escape_string($password)."'")

.NET

En .NET evitaremos la inyección en SQL Server (con C#) estableciendo el tipo de parámetro como literal con SqlDbType.VarChar.

SqlConnection con = new SqlConnection(_connectionString);
SqlCommand cmd = new SqlCommand("SELECT * FROM Usuarios WHERE user=@user AND pass=@pass", con);
/* Convertimos en literal estos parámetros, por lo que no podrán hacer la inyección */
cmd.Parameters.Add("@user", SqlDbType.VarChar, 32).Value = user;
cmd.Parameters.Add("@pass", SqlDbType.VarChar, 64).Value = password;

O también podríamos usar AddWithValue de una forma ligeramente similar a la anterior:

using( SqlConnection con = (acquire connection) ) { 
	con. Open(); 
	using( SqlCommand cmd = new SqlCommand("SELECT * FROM Usuarios WHERE user=@user AND pass=@pass", con) ) { 
		/* Convertimos también en literales los parámetros */
		cmd.Parameters.AddWithValue("@user", user); 
		cmd.Parameters.AddWithValue("@pass", password); 
		using( SqlDataReader rdr = cmd.ExecuteReader() ){ 
			/* [...] */
		}
	}
}

Java

Ahora con Java lo que hacemos es similar a lo que hemos hecho con C# (en .NET), crear la consulta con los parámetros y posteriormente establecerlos (sustituirlos siendo ya estos un literal, que no producirán fallos de seguridad).

Connection con = (acquire Connection) 
PreparedStatement query = con.prepareStatement("SELECT * FROM Usuarios WHERE user=? AND pass=?"); 
query.setString(1, user); 
query.setString(2, password); 
ResultSet rset = query.executeQuery();

Perl

En este ejemplo de Perl usamos la característica placeholder que al fin y al cabo es igual que con los dos ejemplos anteriores, agregando a la consulta los parámetros (con este método se pone a punto las comillas para evitar las inyecciones SQL).

$query = $sql->prepare("SELECT * FROM Usuarios WHERE user=? AND pass=?"); 
$query->execute($user,$password);

Conclusión

Se pueden evitar estos ataques en muchos lenguajes distintos, e incluso hay lenguajes que por defecto hay que complicarse para que exista este fallo de seguridad, pero lo que tenemos que saber es que donde hay una consulta SQL puede haber una brecha de seguridad, por lo que recomiendo prestar un mínimo de atención con estos ataques que están tan de moda, y si alguno quiere comentar como hacerlo de otra forma o con otro lenguaje puede hacerlo en los comentarios, o comentar donde hay otros ejemplos.

Más información | Wikipedia
En Genbeta Dev | Aumenta el interés por los ataques de inyección SQL

Los comentarios se han cerrado

Ordenar por:

30 comentarios