lunes, 30 de julio de 2018

Ataques Web - Demostración - Sql Injection Blind

Este tipo de ataque es similar al SQL Injection que se acaba de estudiar, con la diferencia que la página web no devuelve ningún mensaje de error al producirse resultados incorrectos tras una consulta a la base de datos. Esta falta de muestreo de resultados se produce por el tratamiento total de los códigos de error, y la imposibilidad de modificar, a priori, información alguna de la base de datos, teniendo respuesta únicamente en caso de que la consulta sea correcta.

La falta de mensajes de error no quiere decir que no sea vulnerable una página web. ¿Cómo se sabe que una web es vulnerable a SQL Injection Blind? Pues basta con probar un poco más y siempre que la inyección esté bien ejecutada se mostrará el contenido esperado.

Sentencias condicionales tipo Or 1=1 o having 1=1 ofrecen respuestas siempre correctas (true o verdadero) por lo cual suelen ser usadas por los programadores como formas de comprobación.

En el nivel de seguridad low el código fuente vulnerable es el que se muestra a continuación, la única diferencia con el nivel low de SQL Injection es el tratamiento de errores:

nivel de seguridad low el código fuente vulnerable


DVWA vuelve a mostrar una página similar a la de SQL Injection, donde escribir el ID de un usuario de la base de datos, y al igual que antes, devuelve el nombre y apellido asociado a dicha ID:

devuelve el nombre y apellido asociado a dicha ID


Se prueba con una comilla simple para ver que realmente no se devuelve ningún error y efectivamente al pulsar en “Submit” se vuelve a llevar a la pantalla original en blanco:

prueba con una comilla simple para ver que realmente no se devuelve ningún error

Tras ver que no se devuelve ningún error se pasa a probar a inyectar una consulta de tipo condicional, en este caso se va a insertar ' OR 'x'='x, lo que devolverá un listado con los usuarios:
se pasa a probar a inyectar una consulta de tipo condicional

A continuación se inyectará una consulta más compleja, anidando a la original:
1' and 'test' = 'b' union select database(), user() #
Que debe devolver la base de datos en que se está trabajando y el usuario utilizado:


inyectar una consulta más compleja
En el nivel de seguridad medium el código difiere del anterior en que la id recibida desde el formulario HTML es filtrada a través de la función mysql_real_scape() como se muestra a continuación:




Al igual que en el nivel medium de SQL Injection, DVWA vuelve a restringir el uso de caracteres especiales, por lo que se vuelve a usar la inyección de nivel low ' OR 'x'='x como ejemplo:

nivel medium de SQL Injection

En SQL Injection Blind, como ya se ha mencionado, en caso de error en la consulta no se devuelve nada, ni tan siquiera un mensaje de error advirtiendo del problema:

SQL Injection Blind

Se inyecta otra consulta condicional pero en esta ocasión sin los caracteres especiales:
1 OR 0=0----

Esta consulta devolverá un listado con los nombres y apellidos de los usuarios:
listado con los nombres y apellidos

Como último ejemplo se extraerán todos los campos de la tabla users inyectando:

1 and 1=0 union select table_name, column_name from information_schema..columns where table_name = 0x7573657273

Donde el número hexadecimal de SQL (0x7573657273) representa el nombre de la tabla en que se va a buscar. Este número puede ser muy importante dado a que a priori nadie conoce las tablas que se han creado en el sistema.

úmero hexadecimal de SQL representa el nombre de la tabla


Prevención


Dado que SQL Injection y SQL Injection Blind son a efectos prácticos la misma vulnerabilidad (pero en el caso Blind, sin mensaje de error devuelto en las consultas), las recomendaciones para evitar este tipo de ataques son las mismas:
  • Filtrado en tiempo de ejecución y bajo demanda.
  • Hacer uso de las funciones addcslashes(), mysql_real_escape_string() y stripslashes(), ya explicadas anteriormente, a la hora de filtrar los datos recibidos para realizar la consulta.
  • Uso de la librería mysqli.

viernes, 27 de julio de 2018

Ataques Web - Demostración - XSS Almacenado

XSS stored, también llamado XSS directo o persistente, consiste en embeber código HTML o Javascript en una aplicación web pudiendo llegar incluso a modificar la propia interfaz de un sitio web (defacement). Al igual que en el caso de XSS reflejcted, esta vulnerabilidad compromete la seguridad del usuario y no la del servidor.

La diferencia frente a XSS reflected es que este tipo de vulnerabilidad es persistente (de ahí que se le conozca también por ese nombre) ya que el código malicioso insertado generalmente es almacenado en una base de datos.

A modo de ejemplo, se considera el siguiente sitio web:

Un blog de noticias sobre Informática donde cada artículo permite la inclusión de comentarios por parte de sus usuarios. Una vez enviado un comentario, el contenido de éste será insertado en la base de

datos e inmediatamente visible en la página del artículo.

Tras descubrir cómo inyectar código en la web, las posibilidades que ofrece esta vulnerabilidad al atacante son diversas:


  • Inyectar código que robe las cookies del resto de usuarios.
  • Inyectar código que redirecciona la página web a una página externa.
  • Realizar un deface a la interfaz con el propósito de estropear el diseño web.
  • Troyanizar un gran número de navegadores de usuarios, tomando un control remoto sobre muchos navegadores.

    En el nivel de seguridad low el código fuente vulnerable es el que se muestra a continuación:

    nivel de seguridad low el código fuente vulnerable

    Este script recoge la información enviada a través del siguiente formulario, en el que los visitantes de la web pueden dejar un mensaje con su nombre (a modo de libro de visitas). Ambos campos son filtrados con la función trim() y mysql_real_escape_string() antes de ser insertados en la base de datos.

    Así mismo, el campo correspondiente al mensaje pasa por la función stripslashes() para eliminar las barras en caso de que el mensaje contenga comillas escapadas. Sin embargo no se realizar ningún filtrado para eliminar código HTML que pudiera contener el mensaje…




    no se realizar ningún filtrado para eliminar código HTML

    Una vez que se pulsa en el botón de envío del formulario, el nombre y el mensaje quedan grabados en la base de datos y al volver a cargar la página se mostrarán bajo dicho formulario:



    volver a cargar la página se mostrarán bajo dicho formulario

    Para comprobar si es vulnerable a XSS en el campo textarea mtxMessage esta vez introduciremos un tag HTML con el que lanzar una ventana de alerta Javascript:

    <script> alert("Vulneravilidad low")</script>

    El resultado de esta acción es que el mensaje se ha guardado correctamente en la base de datos y en cada carga de la página del libro de visitas se muestra la alerta esperada:


    vulnerabilidad low

    Un usuario mal intencionado podría, por ejemplo, provocar un deface del sitio web, modificando la estructura de la página pudiendo llegar en algunos casos a hacer ilegible su contenido.
    Por ejemplo, inyectar:

    </div></div></div></div><div>Qué lástima

    provocaría un cambio en la estructura HTML de la página web y, por consiguiente, del aspecto general de la página web:



    cambio en la estructura HTML de la página web


    En el nivel de seguridad medium el código difiere nivel low en el uso de la función strip_tags() para eliminar los tags HTML que pudiera contener el mensaje y el uso de str_replace() para eliminar la etiqueta <script> del campo correspondiente al nombre:



     eliminar la etiqueta <script>


    Mediante la combinación de las funciones strip_tags() y htmlspecialchars() el ataque a través de este campo textarea ha quedado sin efecto como se comprueba en la siguiente figura:



    campo textarea ha quedado sin efecto


    Por su parte, el campo input correspondiente al nombre no es seguro. El único filtro antes de ser insertado a la base de datos es el realizado con la función str_replace() para eliminar coincidencias con el tag <script>. Esta medida se muestra insuficiente debido a que podría hacer uso del mismo tag con la adición del parámetro type, con lo que ya no se produciría coincidencia y pasaría el filtro. Es más, podría incluso inyectarse cualquier otro tag HTML.

    Sin embargo, el código HTML del formulario no permite la inserción de más de 10 caracteres.

    <input type="text" maxlength="10" size="30" name="txtName">

    Esta limitación no supone un problema puesto que, como vimos en la vulnerabilidad CSRF, Firebug permite la edición inline del código fuente de una página web, por lo que a través de esta herramienta eliminaremos ese parámetro del campo input y, por consiguiente, se podrá inyectar cuanto texto permita el tipo de campo definido en la base de datos.

    <SCRIPT language="javascript">window.location="http://webexterna.com";</SCRIPT>




    vulnerabilidad CSRF, Firebug


    Como se observa en la siguiente figura, la entrada con el código inyectado fue insertada en la base de datos:


    código inyectado fue insertada en la base de datos

    Una vez inyectado el código, cada vez que algún usuario intenta cargar la página web, es redireccionado a la página principal del buscador Google España.
    google logo


    Si el filtrado no permitiera la inserción del tag <script> en ninguna de sus formas, se podría haber inyectado la etiqueta <meta> para provocar este mismo efecto:

    <html><meta http-equiv="refresh" content="0;url=http://www.google.es/"></html>

    Prevención


    Para evitar este tipo de vulnerabilidad se recomienda filtrar siempre la información procedente del usuario antes de hacer uso de ella. Generalmente con filtrar los caracteres “<” y “>” sería suficiente, aunque se recomienda también filtrar los nombres de las etiquetas que pueden resultar peligrosas en este tipo de ataque como <script>, <object>, <applet>, <embed> y <form>.

    Por su parte, DVWA en el nivel de seguridad high hace uso de las funciones stripslashes(), mysql_real_escape_string() y htmlspecialchars().


    nivel de seguridad high hace uso de las funciones stripslashes(), mysql_real_escape_string() y htmlspecialchars()



    Las medidas de seguridad para filtrar la información recibida del formulario son las mismas que en el caso de la vulnerabilidad XSS reflejected con la diferencia de que también ejecuta la función mysql_real_escape_string() antes de insertar la información en la base de datos.

    Otra contramedida enfocada a los propios usuarios de páginas web es la de tener el navegador lo más actualizado posible. Por ejemplo el navegador Internet Explorer a partir de su versión 8, introduce como novedad un filtro Anti XSS que detecta posibles manipulaciones de la página mediante la inyección de código en un parámetro de la URL.

    miércoles, 25 de julio de 2018

    Manejo de Roles y Permisos en Jenkins

    Manejo de Roles y Permisos en Jenkins


    Prerrequisitos



    Para poder tener un buen sistema de usuarios y roles, es necesaria la instalación de los siguientes plugins:

    Matrix Authorization Strategy Plugin -
    http://wiki.jenkins-ci.org/display/JENKINS/Role+Strategy+Plugin


    Creación de Roles



    Para ir a la Gestión de Roles dentro de Jenkins hay que ingresar en: “manager Jenkins” -> “Manage and Assign Roles” - > “Manage Roles”:
    Se puede definir roles a nivel global, a nivel de proyecto o a nivel de slave, pero para una primer instancia solo es necesario generar roles a nivel global.




    Veremos tres roles definidos admin, developer y líder, estos serán designados según categoría de cada usuario. Permitiendo a los developer ver resultados y ejecutar cualquier tarea en Jenkins, el rol líder puede hacer lo mismo que el developer además de poder crear, configurar y borrar tareas. El rol admin tiene todos los permisos.

    Asignar Roles a los usuarios



    Para poder asignar roles hay que ir a: “manager Jenkins” -> “Manage and Assign Roles” - > “Assing Roles”:

    Solo es necesario poner el nombre de usuario y luego agregarlo a la lista, para posteriormente a agregarse a la lista poder asignarle el rol correspondiente.

    Existen usuarios genéricos, donde se les puede definir el rol, para todos los usuarios que complan con la misma condición:

    Anonymous: Es el usuario genérico que se utiliza para cualquier usuario que ingrese al sistema sin estar logueado.

    Authenticated: Es el usuario que por medio del LDAP se autentica al servidor Jenkins y no tiene ningún permiso especial asignado.

    martes, 24 de julio de 2018

    Base de Datos SQL Derby - JPA

    Les muestro como configure una base de datos Derby, que es una base de datos relacional, de SQL y simple, que se levanta en memoria y que se puede guardar en archivos dentro del disco rígido local. 

    En principio se debe generar la siguiente estructura:



    El contenido del archivo persistence.xml es el siguiente:

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">
    <persistence-unit name="insta">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <class>com.program.entity.Comments</class>
    <class>com.program.entity.Likes</class>
    <properties>
    <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
    <!-- if you don't have a database already created append ;create=true 
    to end of the jdbc url -->
    <property name="javax.persistence.jdbc.url" value="jdbc:derby:basededatos" />
    <property name="javax.persistence.jdbc.user" value="root" />
    <property name="javax.persistence.jdbc.password" value="root" />
    <!-- if you just created the database, maybe you want hibernate to create 
    a schema for you <property name="hibernate.hbm2ddl.auto" value="create"/> -->

    <!-- <property name="hibernate.hbm2ddl.auto" value="create" /> -->
    </properties>
    </persistence-unit>
    </persistence>

    En javax.persistence.jdbc.url se puede agregar ";create=true" la primera vez como para que cree la base de datos cada vez que se inicia. Una vez que esta creada se debe quitar como para que no borre la base y la vuelva a crear.

    En el pom.xml se debe agregar las librerias para poder usar Derby:

      <dependency>
       <groupId>org.hibernate</groupId>
       <artifactId>hibernate-entitymanager</artifactId>
       <version>3.6.8.Final</version>
     </dependency>
     <dependency>
       <groupId>org.apache.derby</groupId>
       <artifactId>derby</artifactId>
       <version>10.13.1.1</version>
       <scope>runtime</scope>

     </dependency>

    En las entidades se debe utilizar maven como siempre, muestro un ejemplo:

    package com.instadany.entity;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;

    @Entity
    public class Likes {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int id;

    @Column
    public String idinsta;

    }

    lunes, 23 de julio de 2018

    Ataques Web - Demostración - CSRF

    Las vulnerabilidades CSRF se producen cuando un sitio web permite a un usuario autenticado realizar acciones consideradas como “sensibles” sin comprobar que realmente es el usuario quien las está invocando conscientemente. En su lugar, la aplicación simplemente comprueba que la petición proviene del navegador autorizado de dicho usuario.

    De este modo, y dado que los navegadores ejecutan simultáneamente código enviado por múltiples sitios web, existe el riesgo de que un sitio web (sin el conocimiento del usuario) envíe una solicitud a un segundo sitio web y éste interprete que la acción ha sido autorizada por el propio usuario.

    Antes de ser víctima del ataque CSRF, el usuario se identifica con el usuario “admin” y la contraseña “password” para acceder al sistema. Como se observa en las siguientes figuras, en caso de producirse la autenticación en el sistema se muestra un mensaje de bienvenida, por lo que la víctima ya es “confiable” para el sitio web mientras la cookie almacenada en su navegador web con la ID de inicio de sesión no caduque o el usuario cierre la sesión (con lo que ésta sería eliminada).

    login dvwa

    El formulario vulnerable a CSRF se corresponde con la página de DVWA de cambio de contraseña para los usuarios del sistema.


    Para llevar a cabo el ataque utilizaremos la configuración proxy propia del navegador y también el programa que provee OWASP, OWASP CSRFTester Herramienta gratuita (distribuida bajo licencia LGPL) para desarrolladores con la que poder comprobar si los formularios web son vulnerables a este tipo de ataque.

    Para configurar el proxy necesitamos ir a la configuración del Chrome, luego acceder a “Cambiar la configuración del proxy”

    Cambiar la configuración del proxy

    Ir a configuracion de LAN , e ingresar como lo indica la imagen, y luego aceptar.

    Cambiar la configuración del proxy lan

    En primer lugar se activará el proxy que incluye la aplicación FoxyProxy para que capture todo el tráfico web en un puerto determinado, el mismo en que estará escuchando la aplicación OWASP CSRFTester. En este caso el puerto es el 8008.

    Puesto que el cambio de contraseña lo realizará el navegador web de la víctima, el hecho de que el atacante desconozca su contraseña es irrelevante. Simplemente se necesita enviar el formulario para capturar los datos clave que se requieren para llevar a cabo este ataque y que recogerá la aplicación OWASP CSRFTester. Para cada petición se muestran detalles como el método de envío empleado por el formulario (GET o POST) y los parámetros transmitidos por URL.
    En nuestro ejemplo son:
    • password_new: contraseña nueva.
    • password_conf: rescritura de la contraseña para comprobar que el usuario la ha escrito correctamente. En caso de no coincidir ambas no se realiza el cambio de contraseña.
    • Change: parámetro de control para confirmar la petición de cambio de contraseña. Si no es definida en la petición no se realizará el cambio aunque las contraseñas coincidan.

    Los parámetros password_new y password_conf son los que se deberán modificar para que la víctima realice un cambio de contraseña (por otra que desconozca) sin su consentimiento.

    la víctima realice un cambio de contraseña

    Para ello la aplicación OWASP CSRFTester cuenta con una herramienta que genera automáticamente el fichero HTML que realizará la petición de cambio de contraseña basada en la confianza que el sitio web tiene en el usuario autenticado en el sistema.
    cambio de contraseña basada en la confianza que el sitio web

    CSRFTester ofrece otras opciones, como por ejemplo la de realizar la petición de cambio de contraseña de una manera más inadvertida insertando, por ejemplo, una imagen. Obviamente esta imagen no será mostrada al usuario (puesto que el origen no es una imagen) y lo que producirá precisamente es que se genere la solicitud de cambio de contraseña.
    solicitud de cambio de contraseña


    En este ejemplo se hará uso de la ingeniería social y la confianza que el usuario tiene en el atacante para que haga clic en el enlace al documento HTML que llevará a cabo el ataque CSRF.

    En caso de no contar con esta ventaja, se podrían emplear otros métodos como por ejemplo combinando un ataque Man in the middle con DNS Spoofing para servirle una web falsa enlazando con nuestro documento HTML en lugar del sitio web original al que pretendía acceder el usuario.

     Man in the middle con DNS Spoofing

    Una vez el usuario haga clic en el enlace se observa que el navegador web le ha redirigido a la

    página de cambio de contraseña y que no se muestra ningún mensaje referente al cambio de la misma.

    Sin embargo, una vez se ha desconectado del sistema y caduca por tanto la cookie con su inicio de sesión, al volver a intentar autenticarse el sistema le muestra un mensaje de error “Login failed”.

    El nivel medio de seguridad de DVWA introduce como condición que la petición de cambio de contraseña provenga del propio servidor donde está alojada la página web. En caso contrario, la petición será desatendida.


    petición será desatendida


    Para explotar esta vulnerabilidad bastaría con un pequeño script programado en PHP que modifica el encabezado de la petición para que al ser ejecutada por la víctima en un servidor externo,

    Prevención


    DVWA sugiere como método más seguro para evitar este tipo de ataque el requerimiento de la contraseña actual junto con la nueva y la rescritura de la misma. Sin embargo esto sólo sería aplicable para este ejemplo concreto de cambio de contraseña, por lo que para otro tipo de acciones se recomienda el uso de tokens de autorización para cada acción.
    Un ejemplo sería utilizar una palabra secreta y el identificador de sesión del usuario para generar los tokens. Las funciones que se muestran a continuación utilizan un valor de configuración prefijado que contiene una palabra secreta a partir de la cual se generan todos los tickets. Esto permite invalidar en cualquier momento todos los tickets modificando simplemente esta palabra.
    palabra secreta a partir de la cual se generan todos los tickets

    La función de generación recibe el nombre del formulario a securizar y obtiene el token asociado haciendo un hash md5 sobre la concatenación de la palabra secreta, el identificador de sesión del usuario y el nombre del formulario. De esta forma se obtiene un token de autorización para cada usuario y cada acción.
    Para comprobar su validez se realiza la misma acción y se compara el token generado con el token recibido.
    Su inclusión en un formulario HTML se realizaría de la siguiente manera:



    compara el token generado con el token recibido



    De este modo, frente al caso en que se hiciera generando tokens personalices por acción con sesión, se utiliza menos espacio en el servidor y se reducirán los problemas de usabilidad. Sin embargo no se tendrá control sobre el tiempo de validez de los tokens, caducando estos en el momento en el que finaliza la sesión de usuario. El siguiente fragmento de código permite comprobar la validez de un token recibido:


    compara el token generado con el token recibido

    viernes, 20 de julio de 2018

    Ataques Web - Demostración - Sql Inyection

    Como su propio nombre indica, esta vulnerabilidad consiste en inyectar código SQL invasor dentro del código SQL programado con el objetivo de alterar la funcionalidad del programa. Este tipo de intrusión normalmente es de carácter malicioso y, por tanto, un problema de seguridad informática. Un programa o página web que no haya sido validado de forma correcta podrá ser vulnerable y la seguridad del sistema (base de datos) no podrá ser asegurada.

    La intrusión se puede llevar a cabo al ejecutar un programa vulnerable, ya sea, en ordenadores de escritorio o bien en sitios Web.

    La vulnerabilidad se puede producir cuando el programador use parámetros a ingresar por parte del usuario, para realizar una consulta de la base de datos. En esos parámetros es donde se puede incluir el código SQL intruso para que sea ejecutado en dicha consulta.

    El objetivo más común del código intruso es extraer toda la información posible de la base de datos, aunque tienen más usos como puede ser el iniciar sesión con la cuenta otro usuario, subir una shell al servidor, etc.


    DVWA muestra un formulario donde se podrá escribir el número identificativo (ID) de un usuario de la base de datos, devolviendo el script su nombre y apellidos.
    devolviendo el script su nombre y apellidos
    El código que obtiene la id del para la consulta no tiene ningún tipo de filtrado por lo que es vulnerable a este tipo de ataque y se podrá inyectar código SQL. Antes de inyectar código malicioso se vera un ejemplo de cómo funciona la página:

    jemplo de cómo funciona la página

    Una forma rápida y sencilla de ver si la página tiene una vulnerabilidad del tipo SQL Injection es introducir una comilla simple, en el caso de tener este tipo de vulnerabilidad va a devolver un error de SQL:


    tipo de vulnerabilidad


    En la anterior figura se observa que el mensaje devuelto por el servidor es que hay un error de sintaxis en la consulta de SQL, por lo tanto es vulnerable y se puede proceder con una  inyección. Hay que tener en cuenta que no en todos los casos aparece el error, dependerá del tipo de vulnerabilidad que tenga, ya que en inyecciones avanzadas no muestran nada enviando una comilla.
    A continuación se muestran consultas básicas que se usan al hacer este tipo de ataque:
    • 1' OR 1=1----'
    • 1' OR '1' = '1
    • 'OR='
    • ' OR 1=1----'
    • ' OR 0=0 ----'
    • ' OR 'x'='x
    Al probar la inyección con 1'' OR 1=1----'' se muestra todos los usuarios que hay en la base de datos:

    muestra todos los usuarios que hay en la base de datos

    Pese a la restricción de caracteres especiales se sigue teniendo un gran abanico de  posibilidades a la hora de formar una consulta para obtener datos, a continuación se muestra un ejemplo en el que anida la consulta original con otra para poder obtener la contraseña de cada usuario:
    1 UNIION ALL SELECT ffiirstt_name,, password ffrom dvwa..users;;

    obtener la contraseña de cada usuario

    Una vez obtenida la contraseña (encriptada con MD5), basta con dirigirse a algún servicio como el que ofrece la página web http://md5.rednoize.com/ para obtener la contraseña desencriptada. Para ello, se copia la contraseña encriptada y se pulsa en buscar. A modo de ejemplo se muestra la contraseña desencriptada del usuario Gordon:

    encriptada con MD5


    Prevención


    DVWA hace uso en el nivel de seguridad high de algunas funciones PHP para filtrar la información recibida desde el formulario:



    Existen ciertos principios a considerar para proteger aplicaciones de un SQL Injection:
         No confiar en la entrada del usuario.
         No utilizar sentencias SQL construidas dinámicamente.
         No utilizar cuentas con privilegios administrativos.
         No proporcionar mayor información de la necesaria.

    Adicionalmente se recomienda el uso de la librería mysqli puesto que permite la posibilidad de realizar conexiones seguras a la base de datos a través de SSL y ofrece mucha más seguridad frente a la vulnerabilidad SQL Injection.