En el tutorial de hoy, aprenderemos cómo proteger sin problemas su aplicación CodeIgniter (pre 2.0) contra los ataques de falsificación de solicitudes entre sitios. La biblioteca que crearemos hoy automatizará todos los mecanismos de protección, haciendo que su sitio sea más sólido y seguro..
Los ataques de falsificación de solicitudes entre sitios se basan en formularios no protegidos en sus sitios.
Un atacante podría crear un formulario falso en su sitio, por ejemplo, un formulario de búsqueda. Este formulario podría tener entradas ocultas que contienen datos maliciosos. Ahora el formulario no se envía realmente al sitio del atacante para realizar la búsqueda; en realidad, la forma apunta a tu ¡sitio! Dado que su sitio web confiará en que el formulario es genuino, pasa y ejecuta las acciones solicitadas (y quizás maliciosas).
Imagine que un usuario ha iniciado sesión en su sitio y se le redirige al sitio del atacante por algún motivo (phishing, XSS, nombre). El formulario del atacante podría apuntar al formulario de eliminación de su cuenta en su sitio. Si el usuario realiza una "búsqueda" en el sitio de los atacantes, su cuenta se eliminará sin que él lo sepa.!
Existen numerosas formas de prevenir este tipo de ataques..
ENVIAR
solicite, compare el token enviado con el de la tienda y, si difieren, deniegue la solicitud. Sin embargo, su sitio aún necesita ser protegido contra XSS, porque si no lo es, este método se vuelve inútil..Tendremos que hacer tres cosas para cada solicitud:
ENVIAR
Solicitar, validar que el token enviado.. Para hacer esto automáticamente, usaremos los ganchos de CodeIgniter. Los ganchos nos permiten ejecutar todas las acciones en diferentes partes de la solicitud. Necesitaremos tres:
Empecemos. Iremos paso a paso para explicar todo lo mejor posible. Primero, crearemos el método que genere el token, de modo que podamos probar todo correctamente. Crea un archivo en tu sistema / aplicación / ganchos
carpeta llamada "csrf.php
", y pegue el siguiente código:
CI = & get_instance ();
Con suerte, lo que hemos agregado arriba debería parecerte algo básico. Estamos creando una clase, llamada CSRF_Protección
, una variable de instancia para mantener la instancia de CodeIgniter, dos variables estáticas para mantener el nombre del parámetro que almacenará el token y una para almacenar el token en sí para un fácil acceso en toda la clase. Dentro del constructor de la clase (__construir
), simplemente recuperamos la instancia de CodeIgniter y la almacenamos en nuestra variable de instancia correspondiente.
Nota: El "nombre del parámetro" es el nombre del campo que contiene el token. Así que en los formularios, es el nombre de la entrada oculta.
Después del constructor de la clase, pegue el siguiente código:
/ ** * Genera un token CSRF y lo almacena en la sesión. Solo se genera un token por sesión. * Esto debe estar vinculado a un enlace posterior al controlador, y antes del enlace * que llama al método inject_tokens (). * * @return void * @autor Ian Murray * / public function generate_token () // Cargar biblioteca de sesión si no está cargada $ this-> CI-> load-> library ('session'); if ($ this-> CI-> session-> userdata (self :: $ token_name) === FALSE) // Genere un token y guárdelo en la sesión, ya que el antiguo parece haber caducado. self :: $ token = md5 (uniqid (). microtime (). rand ()); $ this-> CI-> session-> set_userdata (self :: $ token_name, self :: $ token); else // Establézcalo en una variable local para un fácil acceso self :: $ token = $ this-> CI-> session-> userdata (self :: $ token_name);
Paso a paso:
FALSO
, entonces el token aún no está presente. Necesitamos asegurarnos de que el token haya sido enviado, y sea válido en caso de que la solicitud sea un ENVIAR
solicitud. Continúa y pega el siguiente código en tu csrf.php
expediente:
/ ** * Valida un token enviado cuando se realiza una solicitud POST. * * @return void * @autor Ian Murray * / public function validate_tokens () // ¿Es esta una solicitud de publicación? if ($ _SERVER ['REQUEST_METHOD'] == 'POST') // ¿Está establecido el campo del token y es válido? $ posted_token = $ this-> CI-> input-> post (self :: $ token_name); if ($ posted_token === FALSE || $ posted_token! = $ this-> CI-> session-> userdata (self :: $ token_name)) // Solicitud no válida, enviar error 400. show_error ('La solicitud no fue válida. Las fichas no coinciden. ', 400);
ENVIAR
solicitud, lo que significa que un formulario fue, de hecho, presentado. Comprobamos esto echando un vistazo a la REQUEST_METHOD
dentro de $ _SERVER
super global. $ this-> CI-> input-> post (self :: $ token_name)
es FALSO
, entonces el token nunca fue publicado. ¡Esta es la parte divertida! Necesitamos inyectar los tokens en todas las formas. Para hacernos la vida más fácil, vamos a colocar dos etiquetas meta dentro de nuestra (Como rieles). De esa manera, podemos incluir el token en las solicitudes AJAX también.
Agregue el siguiente código a su csrf.php
expediente:
/ ** * Esto inyecta etiquetas ocultas en todos los formularios POST con el token csrf. * También inyecta meta encabezados en de salida (si existe) para un fácil acceso * desde marcos de JS. * * @return void * @autor Ian Murray * / public function inject_tokens () $ output = $ this-> CI-> output-> get_output (); // Inyectar en la forma $ output = preg_replace ('/ (<(form|FORM)[^>] * (método | METHOD) = "(post | POST)" [^>] *>) / ',' $ 0', $ output); // inyectar en $ output = preg_replace ('/ (<\/head>) / ',''. "\ n". ''. "\ n". '$ 0', $ salida); $ this-> CI-> output -> _ display ($ output);
display_override
Enganche, necesitamos recuperar la salida generada desde CodeIgniter. Hacemos esto usando el $ this-> CI-> output-> get_output ()
método. ENVIAR
. encabezamiento
(si está presente). Esto es simple, ya que la etiqueta de encabezado de cierre solo debe estar presente una vez por archivo. display_override
gancho, el método predeterminado para mostrar su vista no será llamado. Este método incluye todo tipo de cosas, que no deberíamos, solo con el propósito de inyectar algún código. Llamándolo nosotros mismos resuelve esto. Por último, pero no menos importante, debemos crear los ganchos por sí mismos, para que nuestros métodos sean llamados. Pegue el siguiente código en su sistema / aplicación / config / hooks.php
expediente:
// // CSRF Los enlaces de protección, no los toques a menos que sepas lo que estás haciendo. // // ¡LA ORDEN DE ESTOS GANCHOS ES EXTREMADAMENTE IMPORTANTE! // // ESTO TIENE QUE IR PRIMERO EN LA LISTA DE GANCHOS post_controller_constructor. $ hook ['post_controller_constructor'] [] = array (// Fíjate en "[]", este no es el único hook post_controller_constructor 'class' => 'CSRF_Protection', 'function' => 'validate_tokens', 'filename' = > 'csrf.php', 'filepath' => 'hooks'); // Genera el token (DEBE PASAR DESPUÉS DE QUE SE HAGA LA VALIDACIÓN, PERO ANTES DE QUE EL CONTROLADOR // SE EJECUTE, EL USUARIO DE OTRA MANERA NO TIENE ACCESO A UN TOKEN VÁLIDO PARA FORMULARIOS PERSONALIZADOS). $ hook ['post_controller_constructor'] [] = array (// Tenga en cuenta que "[]", este no es el único hook post_controller_constructor 'class' => 'CSRF_Protection', 'function' => 'generate_token', 'filename' = > 'csrf.php', 'filepath' => 'hooks'); // Esto inyecta tokens en todas las formas $ hook ['display_override'] = array ('class' => 'CSRF_Protection', 'function' => 'inject_tokens', 'filename' => 'csrf.php', 'filepath' => 'ganchos');
post_controller_constructor
gancho, así que tenemos que añadir esos corchetes ("[]
"). Consulte la documentación en los ganchos de CodeIgniter para más información. post_controller_constructor
, genera el token en caso de que aún no se haya generado. formar
y el encabezamiento
. Con un mínimo esfuerzo, hemos construido una biblioteca bastante agradable para nosotros mismos..
Puede usar esta biblioteca en cualquier proyecto, y protegerá automáticamente su sitio contra CSRF.
Si desea contribuir a este pequeño proyecto, deje un comentario a continuación, o bifurque el proyecto en GitHub. Como alternativa, a partir de CodeIgniter v2.0, la protección contra ataques CSRF ahora está incorporada en el marco!