Lineamientos utilizados con CodeIgniter 20x De la documentación (User Guide) de CI-2.0.x http://codeigniter.com/user_guide/libraries/security.html :
1. Filtrado XSS (Cross Site Scripting) Por defecto, CI-2.0.x trae deshabilitado el filtrado XSS ya que el mismo implica una ligera sobrecarga de procesamiento. procesamiento. El filtrado puede ser activado globalmente editando el archivo: application/config/config.php
Buscando la línea: $config['global_xss_filtering'] = TRUE;
ATENCIÓN: El filtrado, activado globalmente se ejecuta automáticamente sobre COOKIES y POST. Para llamar a la función explícitamente explícitamente se debe ejecutar el siguiente código: if ($this->security->xss_clean($file, TRUE) === FALSE) { // file failed the XSS test }
Para ver lo que representa el segundo parámetro parámetro de la función xss_clean(), xss_clean(), leer la Guía de Usuario de CI. Como nota aparte, antes de utilizar los arreglos mágicos $_SERVER, $_POST, $_GET, o $_COOKIE es conveniente utilizar las correspondientes funciones "input" que provee CI: http://codeigniter.com/user_guide/libraries/input.html Además, algunas de dichas funciones permiten como segundo parámetro (opcional) especificar especificar explícitamente si ser quiere realizar un filtrado XSS sobre dicho INPUT. Por ejemplo // Al obtener los datos de $_POST['some_data'], previo filtrado XSS $sd = $this->input->post('som $this->input->post('some_data', e_data', TRUE);
Utilizar codificación además de lo visto arriba, por que no hace chequeos sobre el código javascript en su totalidad: $myvar = urlencode($this->input->post(“myvar”)); $this->load->view(“myview”, array(“myvar” => $myvar));
fuente: http://ponderwell.ne http:// ponderwell.net/2010/08/ t/2010/08/codeignite codeigniter-xss-protectio r-xss-protection-is-good-but-not-en n-is-good-but-not-enough-byough-byitself/
2. Cross-site request forgery (CSRF) El destino más habitual de una vulnerabilidad CSRF son los formularios, según lo que se puede leer en: http://www.beheist.com/index.php/en/blog/csrf-protection-incodeigniter-2-0-a-closer-look . Un formulario que presenta vulnerabilidades CSRF generalmente acepta las peticiones o datos enviados al mismo sin chequear si los datos fueron cargados desde un formulario presentado desde la aplicación. Es decir, un atacante que se aproveche de CSRF tratará de enviar datos por POST/GET a un formulario directamente y sin utilizar los formularios de la aplicación. Para (en parte) prevenir estas situaciones, se recomiendan los siguientes 2 pasos: 1. Editar el archivo: 2. application/config/config.php
y activar la opción: $config['csrf_protection'] = TRUE;
3. Utilizar del Helper para formularios (Form Helper) la función: 4. form_open()
Esta función insertará automáticamente en un campo oculto un TOKEN. Luego, al procesar el formulario, se debe verificar la existencia del TOKEN para poder comprobar que la petición provino realmente del formulario en cuestión .
Para ver cómo emplear esta característica en sitios que utilicen AJAX: http://aymsystems.com/ajax-csrf-protection-codeigniter-20
3. Verificación de nombres de archivos Cuando se aceptan nombres de archivos desde alguna entrada de usuario, aplicarle la función "sanitize_filename()" para prevenir lo que se denomina directory traversal (acceso a otros directorios). Cabe aclarar que esto además debe estar respaldado por una la correcta/correspondiente configuración de Apache o servidor HTTP. Por ejemplo, para "sanitizar" un nombre de archivo proveniente desde $_POST['filename']: $filename = $this->security->sanitize_filename($this->input>post('filename'));
4. Encriptación de los datos de sesión en las COOKIES Es altamente recomendable revisar en el archivo de configuración: application/config/config.php
Las siguientes opciones: 1.
sess_encrypt_cookie: Preferentemente debe poseer el valor TRUE en el entorno
de producción. 2. 3.
sess_expire_on_close : Ídem anterior. sess_expiration: Duración de la sesión en segundos (por
7200 Segs).
defecto es de 2 Hs =
NOTA IMPORTANTE: Tal como explica la documentación de CI, el manejo de la sesión que mediante las funciones que incluye CI no hacen uso de las funciones nativas de PHP para le manejo de sesiones .
5. Manejo de datos "de ingreso" al sistema, o "que deben ser mostrados al usuario" Por regla general se debe desconfiar al 100% de los datos que provengan del usuario (también se debe desconfiar de algunos datos almacenados, pero ya se verá esto más adelante). Antes de utilizar o almacenar algún valor que provenga de la entrada de usuario, dicho valor: 1. Debe ser siempre validado a través de la librería de CI, 2. No debe utilizarse nunca directamente en alguna sentencia que involucre "comillas mágicas" (aunque esta característica se encuentra marcada como DEPRECATED en PHP-5.3.0), 3. ... Si los datos deben ser mostrados en pantalla, por ejemplo cuando se debe REPOPULAR UN FORMULARIO, es conveniente filtrar los datos antes de mandarlos a la salida (antes de enviarlos a un 'echo'), utilizando algunas de las siguiente funciones de PHP: 1. 2. 3.
htmlspecialchars(), http://ar.php.net/htmlspecialchars . o, htmlentities(), http://ar.php.net/manual/es/function.htmlentities.php , Funciones prepping de CI, http://codeigniter.com/user_guide/libraries/form_validation.html#preppingdata hay que buscar ejemplo de cómo se utilizan estas funciones en situaciones que NO sean el procesado de formularios)
Estos filtrados previos deben realizarse con el fin evitar mostrar por pantalla contenido entre etiquetas especiales como . De esta forma, prevenimos la
inyección de código que pueda explotar vulnerabilidades XSS/CSRF que pueda ser ejecutado en el navegador del usuario.
Escapar esto caracteres mediante entidades HTML evita el interpretado de los mismos .
6. Evitar SQL injection Las consultas deben realizarse usando Query binding: http://codeigniter.com/user_guide/database/queries.html
Ademas los elementos de la consultas deben ser parámetros. Tampoco hay que incluir magic quotes. Ejemplo : //INSEGURO $this->db->query("SELECT username FROM user WHERE id='$idUsuario'"); //SEGURO $this->db->query('SELECT username FROM user WHERE id=?', array($idUsuario));
Ejemplos : http://stackoverflow.com/questions/1615792/does-code-igniter-automatically-preventsql-injection http://stackoverflow.com/questions/3797613/sql-injection-and-codeigniter
Convenciones generales de desarrollo 1. Interacción con Base de Datos Si la aplicación involucra la utilización de una DB, deberá crearse un usuario y una DB dentro del motor de DB correspondiente y para uso exclusivo de dicha aplicación. Si el framework en uso provee funciones especiales para realizar consultas a la DB (evitándonos escribir código SQL directamente), entonces usar dichas funciones que brinda el framework . Por ejemplo CI provee algunas funciones para interactuar con la DB, mediante la implementación de un patrón que se denomina "Active Record".
2. Diseño/implementación de restricciones en las aplicaciones En general, la seguridad/restricción que se aplica sobre el contenido de la aplicación no se implementa mediante la "OCULTACIÓN DE CONTENIDO". Lo que suele utilizarse es directamente la CANCELACIÓN DEL PROCESO/EJECUCIÓN del script que se está llamando en la solicitud del usuario. Por ejemplo, en CI suelen chequearse los privilegios del usuario (o auntenticar el mismo) en el constructor de un Controller. Si el usuario NO posee los privilegios necesarios, directamente se lo redirige a un controlador especial SIN MOSTRAR CONTENIDO ALGUNO del Controller que quiso acceder originalmente.
3. Comentarios dentro del código PHP/HTML Si los comentarios están relacionados con los usuarios/permisos/privilegios u otra información delicada, es preferible documentar dicha información en la Wiki del proyecto. Es desaconsejable comentar dichos datos en PHP, y es un error comentar dicha información en HTML (ya que esto último sólo oculta dicha información a la vista del usuario, pero es visible en el código fuente HTML).
4. Ejecución de comandos externos a PHP Cuando se ejecuta un comando externo a un script PHP, deben validarse los parámetros que se le pasan a la aplicación. Particularmente, debe determinarse qué cosas se le pasará como argumentos a dicha aplicación y descartar todo lo demás.
5. Evitar envenenamiento de Cookies
El contenido de las cookies debe estar encriptado y debe almacenarse en ellas la direccion del usuario(IP)(para validación). Fuente: http://stackoverflow.com/questions/1633062/how-to-prevent-cookie-poisoning
LINKS XSS: http://stackoverflow.com/questions/1996122/how-to-prevent-xss-with-html-php http://stackoverflow.com/questions/71328/what-are-the-best-practices-for-avoiding-xssattacks-in-a-php-site http://ha.ckers.org/xss.html SQLi: http://ha.ckers.org/sqlinjection/
Convenciones a utilizar con usuarios de prueba 1. Nombres de usuario y passwords Los usuarios de prueba que posean privilegios de administrador en los sistemas en desarrollo, deberán tener passwords no triviales: 1. Formadas por caracteres y números, 2. Fáciles de recordar, 3. En lo posible que posea algún carácter raro (pero permitido por la aplicación) 4.
Documentar los datos de dichos usuarios en la Wiki del proyecto correspondiente, especificando si el usuario será válido en los entornos de
DESARROLLO/PRUEBA/PRODUCCIÓN. Por ejemplo, si la aplicación se llama SSD, un usuario y password de ejemplos podrían ser: username: admin password: pss2011tcw.ssddmn // Notar que el pass es en realidad es la cadena "pass2011tcw.ssdadmin" SIN LAS VOCALES
Suponiendo que se utilicen varios usuarios de prueba, dicha cantida de usuarios deberá mantenerse mínima (y controlarse al momento de desplegar el sistema en el entorno de PRODUCCIÓN/PRUEBA).
Bibliografía/documentación sobre riesgos en aplicaciones web: •
OWASP Top Ten Project: https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project
El Proyecto OWASP (Open Web Application Security Proyect) provee un rankinglistado de los 10 riesgos presentes en la mayoría de las aplicaciones web anualmente. Cabe aclarar que dicho listado expone un ranking de riesgos y no de ataques a aplicaciones web. Esta diferenciación entre los concepts "riesgo/amenaza y ataque" se debe a que el ránking también pondera otras características del riesgo como puede ser el grado de influencia en el sistema víctima (por ejemplo una amenaza puede realizar alteraciones leves de datos, mientras que otra amenaza puede representar una pérdida total de datos).