5 de marzo de 2011

Cómo evitar el SQL injection en Java y C#

Una de las amenazas más peligrosas del primer tipo de los OWASP top 10 de 2010, es decir de las amenazas que se refieren a inyecciones de código, son precisamente las temidas inyecciones SQL. Si no conoces su funcionamiento antes de continuar puedes ir a http://tecnologiasweb.blogspot.com/2008/07/sql-injection-el-enemigo-ms-peligroso.html y luego regresar a este artículo.


Prevenirlas no ha sido fácil, sobretodo porque muchos programadores han querido filtrar los caracteres que reciben antes de crear las consultas, y en ese caso suceden dos cosas: O no siempre se filtran todos los caracteres perjudiciales que pudieran intervenir en una inyección de código SQL, o se filtran algunos caracteres que pudieran ser de uso común, por lo que se le restringe la usabilidad al usuario.


Las soluciones definitivas y conocidas para este flagelo pasan primordialmente por usar métodos que no puedan confundir parámetros con comandos. El primero de estos métodos es el uso de consultas parametrizadas. ¿Que es una consulta parametrizada? Pues lo mejor en este caso es un ejemplo, empecemos con Java:

   // '?' el símbolo indica la ubicación del parámetro
   querySQL = 
   conn.prepareStatement("SELECT nombre FROM empleados WHERE salario > ?");


   // Completando la consulta
   // Note que se empieza con "1" para el primer parámetro
   querySQL.setInt(1, 350);
   rs = querySQL.executeQuery();
}
   catch(Exception ex)
{
   System.err.println("Excepción de base de datos: " + ex);
}

Como se puede observar en el lugar del parámetro que convencionalmente colocaríamos se ha colocado un signo de interrogación, y el método PreparedStatement.setInt() coloca en el primer parámetro un entero igual a 350.  No hay manera de que se pueda colocar otra cosa en el contenedor que no sea un entero. Si fuera una cadena aunque esta llevara caracteres dañinos, estos no serían jamás tratados como código precisamente por haber sido "parametrizados".
En C# el proceso es parecido:
SqlCommand command = connection.CreateCommand();
command.CommandText = “SELECT * FROM Customers WHERE CustomerID = @CustomerID“;
command.Parameters.Add(
       new SqlParameter(“@CustomerID“, SqlDbType.NChar, 5)).Value = "GSDC3"
En este caso simplemente hemos introducido un parámetro SQL precedido por el arroba (@) "@CustomerID" y lo cargamos con su valor correspondiente con el método command.Parameters.Add()
El segundo método de prevención consiste en desarrollar procedimientos almacenados (stored procedures) directamente en la base de datos SQL. Si bien este método es más complejo, agrega una capa de seguridad adicional a la aplicación ya que los procedimientos almacenados al ser objetos de SQL pueden ser tratados independientemente cada uno con una permisología aparte además de colocar la lógica de manejo de la base de datos en la misma base de datos.

No hay comentarios.:

Entradas populares