Análisis Forense Informático, Ciberseguridad, Formación
Cuando publicamos un sitio web en internet dinámico con PHP y MySQL estamos abriendo la puerta a que cualquier persona del mundo pueda ver la información que presentamos, pero también nos exponemos a todo tipo de ataques del exterior. Hoy vamos a ver cómo protegernos de la tercera vulnerabilidad más atacada del mundo según OWASP 2021: las inyecciones de código, en concreto, de SQL.
En este caso práctico nos situamos en el equipo de seguridad encargado de defender el servidor de los atacantes, el denominado Blue Team.
Las principales funciones del blue team son realizar evaluaciones de las distintas amenazas que puedan afectar a las organizaciones, monitorizar la red, los sistemas, etc. y recomendar planes de actuación para mitigar los riesgos.
La inyección SQL es un tipo de ataque encubierto en el cual un hacker inserta código propio que se ejecutará en la base de datos del servidor web, pudiendo conseguir información sensible de la base de datos o incluso llegando a borrar contenidos de la misma.
Si un desarrollador web no es meticuloso, al crear un sitio podría dejar un resquicio que alguien con malas intenciones podría usar para provocar efectos inesperados en su base de datos. Las inyecciones de SQL (o SQLI) se producen cuando el hacker introduce o inyecta en el sitio web código SQL malicioso, un tipo de malware que se conoce como la carga útil, y consigue subrepticiamente que envíe ese código a su base de datos como si de una consulta legítima se tratara.
Para esta práctica se ha utilizado como entorno una máquina virtual Debian 11 con un Stack LEMP sobre el que realizaremos una instalación de una versión antigua de PHP, 5.6, para ser inicialmente vulnerables a las inyecciones de código SQL.
Después veremos cómo bastionar nuestro código para evitar este tipo de ataques.
Aunque la última versión disponible de PHP en la fecha de realización de esta entrada es 8.1, para este caso práctico utilizaremos la descontinuada versión 5.6 ya que es la última que contiene las funciones de PHP que utilizaremos para crear un sitio web vulnerable a inyecciones SQL, como por ejemplo mysql_connect para establecer la conexión con nuestra base de datos.
Cuando hemos desplegado nuestros sitios web en PHP y MySQL, como vemos en el video, éstos son vulnerables a los ataques por inyección SQL. Veamos por ejemplo cómo atacar el formulario de acceso POST con una simple instrucción que introduciremos en el campo de nombre de usuario:
' OR 1=1 -- -
Para entender por qué esto funciona analizaremos el código PHP del formulario de recepción, viendo el extracto de las líneas de código que hacen que la inyección funcione:
$username = $_POST['username']; $passwd = $_POST['passwd']; $result = mysql_query("SELECT nombre,apellidos,password FROM usuarios WHERE nombre='" . $username . "' and password='" . $passwd . "';");
Como podemos ver, se está concatenando directamente el valor recibido en los campos del formulario en la sentencia SQL que se va a ejecutar. El problema viene cuando alguien escribe en el formulario el cierre de la condición y añade otra, provocando que el código SQL que realmente se ejecute en MySQL sea el siguiente:
SELECT nombre,apellidos,password FROM usuarios WHERE NOMBRE='' OR 1=1 -- -
Como vemos, la condición 1=1 siempre se cumple, por lo que automáticamente ganaremos acceso al sitio web.
En el caso de la página web de tipo GET, lo que está recreando aquí nuestro PHP es una página en la que se muestran contenidos buscados por el identificador que los almacena en MySQL, como puede ser una página de información de usuarios. En este caso vamos a utilizar una inyección SQL que hace uso de UNION para combinar los resultados y no obtener la información de un solo usuario, si no de todos a la vez:
-1 UNION SELECT GROUP_CONCAT(idusuario), GROUP_CONCAT(nombre), GROUP_CONCAT(apellidos), GROUP_CONCAT(password) FROM% usuarios #
Nuevamente, vamos a observar el código PHP para entender qué está ocurriendo aquí y por qué nuestra inyección tiene éxito sobre MySQL:
$id = $_GET['id']; $result = mysql_query("Select * from usuarios where idusuario=" . $id . ";");
Al igual que ocurría en la web con POST, nuestra sentencia SQL está concatenando directamente el valor de la variable recogida en la URL, por lo que la inyección tiene éxito. En este caso empiezamos con un valor negativo para que la primera parte de la sentencia SQL no devuelva ningún resultado y así el resultado renderizado por PHP sea el de nuestro UNION.
Como hemos visto en el vídeo, siendo conscientes de las amenazas de nuestro entorno y cuidadosos a la hora de desarrollar podemos protegernos fácilmente frente a amenazas como las inyecciones SQL.
Es crucial tratar de mantener nuestro software actualizado para evitar en gran medida las amenazas: si actualizáramos nuestra instalación de PHP 5.6 a una versión actual dejaríamos de ser vulnerables a las inyecciones SQL porque el propio motor de PHP ha eliminado las funciones que podían explotar estas vulnerabilidades.
Blue Team, Ciberseguridad, LEMP, MySQL, PHP, Puesta en Producción Segura, SQL injection
Comments RSS Feed