Tuesday, December 30, 2014

SQL Injection - example using C# and MySQL


At this post we see a simple SQL injection example using a C# app and MySQL as database manager.

First steps:

In MySQL we already have an "ejemplo" (example) database and a "login" table, our login table has 2 rows (each row is a unique user); 1st user name is "alfonso" and its  password is "123", 2nd user name is "jesus" and its password is "456".

After we create our project we need to set-up our database connection

In our Visual Studio project, our application will verify if exists a record in our database matching user name and password typed in a "user textbox" and a "password textbox", this verification is made trough a SQL query:

SELECT * FROM login WHERE usuario='username' AND pass='password';

In our C# code we have an "Autenticacion" (autentication) function; this function accepts a SQL query as parameter and returns a Boolean value indicating if our queries has returned at least one row:

public bool Autenticacion(string query)
{
 bool nivel;
 MySqlCommand miComando = new MySqlCommand(query, this.miConexion);
 MySqlDataReader miLector;

 miLector = miComando.ExecuteReader();
 if (miLector.Read())
 {
  nivel = true; // si la consulta SQL devuelve algun  registro
  miLector.Close();
 }
 else
 {
  nivel = false; //los datos no coinciden
  miLector.Close();
 }
 return nivel;
}


This function is called from main form, where user name and password are replaced with information typed by users. Our example will show the complete query to execute only as educational purpose.

Our button "Ver instrucción" allows us to print into our form the SQL query El boton Ver instrucción imprime en pantalla el contenido de la consulta SQL que se mandará como parametro a la función autenticación:

private void button1_Click(object sender, EventArgs e)
{
 q = "SELECT * FROM login WHERE usuario='" + textBoxUsuario.Text + "' and pass='" + textBoxContra.Text + "';";
labelSQL.Text = q;
}


El botón Ejecutar Instrucción ejecuta la función autenticación con la consulta SQL como parametro y si la función autenticación devuelve un valor verdadero, muestra en pantalla un mensaje que indica que el usuario si se encuentra registrado; si por el contrario, la función devuelve un valor falso, se muestra en pantalla un mensaje que indica que los datos no se encontraron dentro de la base de datos.

Ejemplos de Inyección SQL


En nuestro formulario, si introducimos como alfonso como usuario y 123 como contraseña y damos clic sobre el botón Ver instrucción SQL, podemos observar la consulta SQL tal y como se enviaría a la función autenticación:

SELECT * FROM login WHERE usuario='alfonso' AND pass='123';



y si presionamos el botón Ejecutar instrucción, esta consulta SQL se envia como parametro esta consulta. Podemos observar que se muestra en el formulario que el usuario si cuenta con derechos de acceso.








Si modificamos la contraseña y ahora ponemos 456 como contraseña y presionamos el botón Ver instrucción SQL, observamos que la consulta SQL quedaria asi:

SELECT * FROM login WHERE usuario='alfonso' AND pass='456';

Si en este momento presionamos el botón Ejecutar instrucción, recibiremos de parte de la función autenticación un valor falso, y esto muestra en el formulario un mensaje de que el usuario no tiene derecho de acceso.




Comencemos con en el ejemplo:

Al momento de ingresar un nombre de usuario, podemos engañar al sistema si utilizamos la comilla simple en el cuadro de texto y a la vez escribimos con una operación OR alguna condición que siempre de como resultado un valor verdadero (ejemplos: 1=1, 5=5, 5>1, 1<2 -="">SELECT * FROM login WHERE usuario='as' or '2'='2' AND pass='as' or '9'='9';


en esta instrucción tenemos operaciones de tipo OR que siempre dan en verdadero, ya que '2' es igual a '2' y '9' es igual a '9', esto ocasiona que siempre se devuelvan registros de la consulta (siempre y cuando existan registros en la tabla), y ya que la consulta SQL devuelve por lo menos un registro, la función autenticación devolverá un valor verdadero, esto podrá otorgarle acceso al sistema sin que realmente tenga los derechos de accesar.

Otra forma de obtener el acceso al sistema mediante inyeccion SQL es utilizar la capacidad de poder hacer comentarios en las sentencias SQL, de esta forma aprovechariamos el no tener que escribir contraseña alguna, de esta forma podriamos escribir algo como esto:

usuario: t' and 2=2;--
contraseña:

y la consulta SQL quedaria de esta forma:

SELECT * FROM login WHERE usuario='t' or 2=2;-- and pass='';

ya que utilizamos el simbolo de comentarios (--), todo lo que va después del simbolo de comentarios es ignorado por el sistema de base de datos, es como se no se escribiera, lo que nos da una sentencia SQL asi:

SELECT * FROM login WHERE usuario='t' or 2=2;

y ya que utilizamos una operacion de tipo OR en donde siempre da un resultado verdadero, obtenemos por lo menos un registro y la función autenticación nos permite el acceso del atacante aunque realmente no tenga derechos de acceso.

Actualización (21 Agosto 2013):
Un video que muestra que hasta las instituciones de gobierno sufren este tipo de problemas, realmente recomiendo verlo en pantalla completa para alcanzar a visualizar el texto que introducen.