Seguridad WEB Inyección de código Maestría en TICs – 2015 Énfasis Auditoría y Seguridad Informática Seguridad en aplicaciones y base de datos Cristian Cappo ([email protected]) NIDTEC - Núcleo de Investigación y Desarrollo Tecnológico - FPUNA Aplicación del lado servidor Se ejecuta en un servidor web (app server) Toma la entrada de los usuarios remotos vía el navegador Interactúa con base de datos y otros servidores Prepara la salida para los usuarios 2 Ejemplo: PHP (Hypertext Processor) Lenguaje scripting con sintaxis al estilo C Puede intercalar HTML estático y código <input value = <?php echo $myvalor; $>> Puede incrustar variables de cadenas con comillas dobles: $usuario=“Mundo”;echo “Hola $usuario!”; o $usuario=“Mundo;echo “Hola”. $usuario.“.”; Datos de formularios en arreglos globales _$GET, $POST, .. 3 Inyección de código en PHP Calculadora server-side en PHP: $in = $_GET[‘val’]; eval(‘$op1=‘. $in. ‘;’); Entrada benigna http://victima.com/calc.php?val=5 Entrada maliciosa http://victima.com/calc.php?val=5;system(‘rm *.*’) Calc.php ejecuta: eval(‘$op1=5; system(‘rm *.*’);’); 4 Mas inyección de código en PHP Código PHP para enviar mail $email = $_POST[“email”] $subject = $_POST[“subject”] system(“mail $email –s $subject < /tmp/texto”) Código atacante http://victima.com/mail.php? [email protected]& subject=foo < /usr/passwd; ls http://victima.com/mail.php? [email protected]&subject=foo; echo “evil::0:0:root:/:/bin/sh">>/etc/passwd; ls 5 SQL Típica generación de código usando SQL $selecteduser = $_GET['user']; $sql = "SELECT Username, Clave FROM users " . "WHERE Username='$selecteduser'"; $rs = $db->executeQuery($sql); Que pasa si ‘user’ es una cadena maliciosa que cambia el significado de la consulta? 6 Típico login 7 Ingrese Usuario & Navegador Password Servidor (Cliente) web SELECT passwd FROM USERS WHERE uname = ‘$user’ DB 8 Login “normal” Ingrese Usuario & Navegador Password Servidor (Cliente) web SELECT passwd FROM USERS WHERE uname = ‘smith’ DB 9 Entrada maliciosa 10 Inyección SQL (SQLI) Ingrese Usuario & Navegador Password Servidor (Cliente) web SELECT passwd FROM USERS WHERE uname = ‘’; DROP TABLE USERS;--’ DB 11 12 Inyección SQL – Idea básica Servidor víctima Atacante 1 2 3 Recibe datos desde la DB Consulta No esperada Esta es una vulnerabilidad de validación de entrada La entrada de usuario no sanitizada cambia el sentido original de la consulta SQL. Es un caso especial de inyección de código DBMS Victima slide 13 Autenticación con la BD set UserFound=execute( “SELECT * FROM UserTable WHERE username=‘ ” & form(“user”) & “ ′ AND password= ‘ ” & form(“pwd”) & “ ′ ” ); El usuario ingresa su código y contraseña, este SQL chequea si existe tal combinación en la BD. If not UserFound.EOF Autenticación correcta else Autenticación incorrecta 14 Usando SQLI para ingresar El usuario ingresa ′ OR 1=1 - El aplicación web ejecuta la consulta set UserFound=execute( SELECT * FROM UserTable WHERE username=‘’ OR 1=1 -- … ); Ahora todos los registros son retornados y la autenticación es correcta 15 Más de SQLI El usuario puede dar como código ′ exec cmdshell ‘net user badguy badpwd’ / ADD – Y se ejecuta la consulta: set UserFound=execute( SELECT * FROM UserTable WHERE username= ‘’ exec … -- … ); Crea una cuenta para badguy en el servidor de base de datos. 16 SQLI de segundo orden Los datos guardados en la BD pueden ser utilizados luego para un SQLI Por ejemplo, un usuario cambia su nombre a admin’- Esta vulnerabilidad puede existir si no se aplica consistentemente la validación de entrada y el escapado (por ejemplo de ’ convertir a \’) Algunas aplicaciones solo validan la entradas del servidor web y no así las entradas que vienen de la BD. UPDATE users set password =‘jejeje’ where uname =‘admin’--’ Tratar a todas las entradas como peligrosas 17 Previniendo los SQLI Validar toda la entrada Filtrar cualquier carácter que tenga un significado especial Chequear el tipo de dato Caracteres permitidos (whitelist) Colocar solo los no permitidos a veces no funciona Se puede olvidar algunos Puede prevenir entradas válidas (por ejemplo O’Higgins) Permita solo un conjunto bien definido de valores seguros Puede utilizar expresiones regulares. 18 Escapando Caracteres especiales como ‘ provee distinción entre datos y código en la consulta Para entradas válidas con ‘ , use caracteres escapados. Diferentes BD tienen diferentes reglas de escapado: Ejemplos escape(O’Higging) = O\’Higging escape(O’Higging) = O’’Higging 19 Sentencias SQL precompiladas En un SQLI los datos son interpretados como código Variables bind : garantiza que los lugares en la consulta sean datos (no código) Sentencias prepared: permiten la creación de consultas estáticas con variables bind. Preserva la estructura de la consulta prevista. 20 Ejemplo de sentencias prepared /* Ejemplo en Java */ PreparedStatement ps = db.prepareStatement("SELECT pizza, toppings, quantity, order_day " + "FROM orders WHERE userid=? AND order_month=?"); ps.setInt(1, session.getCurrentUserId()); ps.setInt(2, Integer.parseInt(request.getParamenter("month"))); ResultSet res = ps.executeQuery(); Variables bind (data placeholder) La consulta es parseada sin los parámetros Las variables bind tienen tipos (int, string, …) De todos modos debe seguir cuidando los SQLI de segundo orden. 21 SQL Injection Cheat Sheet http://ferruh.mavituna.com/sql-injectioncheatsheet-oku/ Recopilación de “tips” y “trucos” para Inyección SQL teniendo en cuenta tipo de DBMS (MySQL, MS SQL Server, Oracle , PostgreSQL) 22 XSS (un poco más) Web 2.0 1. HTTP GET 2. HTML and JS ` 3. Asynchronous GET 4. Javascript to wrap in eval Los scripts maliciosos pueden estar Contenidos en argumentos de JavaScript creados dinámicamente. Contenido en los arreglos JavaScript Escritos dinámicamente en el DOM 23 XSS en AJAX Flujos en arreglos Javascript var downstreamArray = new Array(); downstreamArray[0] = “42"; doBadStuff(); var bar=“ajacked"; No detectado por filtros simples No existe <>, “script”, on.., etc Solo se necesita romper la doble comilla 24 XSS en AJAX Código JSON escrito en el DOM por un script del lado cliente var inboundJSON = {"people": [ {"name": "Joel", "address": “<script>badStuff();</script>", "phone": "911"} ] }; someObject.innerHTML(inboundJSON.people[0].address); // Vulnerable document.write(inboundJSON.people[0].address); // Vulnerable someObject.innerText(inboundJSON.people[0].address); // Seguro XSS puede estar en el DOM document.url, documento.location, document.referer 25 Protegerse contra XSS Asegurar que su aplicación valide todas las cabeceras, cookies, query string, campos de formulario y campos ocultos No intentar identificar contenido activos y removerlos, filtrarlos o sanitizarlos. Existen demasiados tipos de contenido activo y muchísimas formas de codificarlo para sobrepasar los filtros. Es recomendable utilizar una política de seguridad positiva que especifica que es lo que está permitido. La política de seguridad negativa (mantenimiento de firmas) son difíciles de mantener y usualmente incompletas. 26 Prevenir XSS Cualquier entrada del usuario debe ser preprocesada antes de utilizarla dentro de HTML Remover /codificar los caracteres especiales HTML Usar una buena librería de escape Ejemplo: OWASP ESAPI En PHP, htmlspecialchars(string) puede reemplazar todos los caracteres con sus códigos HTML ‘ se convierte a &#039; “ se convierte a &quot; & se convierte a &amp; En ASP.NET, Server.HtmlEncode(string) 27 Bibliografía M. Zalewski. The tangled Web. A guide to securing Modern Web Applications. 2012. M. Shema. Hacking Web Apps. Detecting and Preventing Web Application Security Problems. Syngress Press. Elsevier. 2012. P. Hope & B. Walther. Web Security Testing Cookbook. O’Really Media Inc. 2008. 28 ¡Gracias! ¿Preguntas? 29