2011-02-01 9 views
25

Estoy haciendo un sistema con CakePHP que necesita ser decentemente seguro, porque estamos tratando con dinero, cuentas de clientes, etc. Hasta ahora todo ha estado funcionando bien, hasta que tuve que integrarme con una plataforma de pagos en la que Necesito redireccionar a su sitio y me redirigen a la mía.¿De qué está protegiendo la session.referer_check de PHP?

Esto funciona bien en mi máquina de desarrollo (depuración = 2), pero en producción, cuando se redirige al cliente, recibe un aviso de inicio de sesión en lugar de volver a su "área de inicio de sesión". Después de excavar, descubrí que esto se debe a que CakePHP establece session.referer_check, lo que invalida las sesiones si el HTTP_REFERER proviene de otro servidor que no sea el mío.

Ahora, normalmente, desactivo esto sin pensarlo dos veces, pero en este sistema estoy un poco más preocupado por la seguridad de lo normal.

Mi pregunta es ¿de qué se supone que me debe proteger session.referer_check?
¿Qué tipo de ataque/ataque/malo se puede hacer en mi sitio si lo desactivo?

Supongo que debe haber alguna razón por la que esto existe, pero no puedo imaginar de qué me protegería.

¿Podría darme alguna idea?
¿Es seguro desactivar esto?

Gracias
Daniel

+0

¿Está 100% comprobando la referencia y no un token enviado con formularios en una solicitud previa para protegerse contra CSRF? – Pablo

+0

100% seguro. CakePHP no está verificando el referente, solo está activando un referer_check (una característica de PHP que verifica el referente mismo: http://www.php.net/manual/en/session.configuration.php#ini.session.referer-check) - Además, el resultado que veo es desconectar a la gente. Lo que hace CakePHP cuando no le gusta el token CSRF (o cuando no lo tiene) es "blackholing" (página en blanco, básicamente) –

+0

Similar: http://stackoverflow.com/questions/22079477/cakephp -session-is-lost-after-an-oauth-redirect – trante

Respuesta

22

Esto es para proporcionar protección limitada para Session Fixation y CSRF/XSRF. Comprobando el referer es a valid method of stopping xsrf. Un mejor método para detener la fijación de sesión es Session.use_only_cookies, porque un pirata informático no puede establecer una cookie en un navegador de víctimas para un dominio que aún no controla.

Sin embargo, Session.referer_checkes fácil de puentear. Solo busca una subcadena en el dominio de referencia. Si la subcadena falta totalmente, lo que sucede si la URL de origen es https: //, la identificación de la sesión no será válida. Sin embargo, debido a que es una subcadena y no una cadena completa, puede omitir esto para www.somedomain.com haciendo referencia al www.somedomain.com.some_hacker.com. En resumen, creo que esto es completamente inútil.

+0

¡Muchas gracias por su respuesta! Esto lo aclara! –

3

Comprobación del árbitro de esta manera puede ayudar a proteger contra Cross-site request forgery.

Lo ideal sería que deseara una forma de que la comprobación del referer coincida con su propio dominio o el dominio de la plataforma de pago, pero como es una verificación de subcadena simple en lugar de una coincidencia de patrón, no creo que esto sea posible.

Si deshabilitó esto debe poner otras medidas en su lugar para protegerse contra tales ataques.

+0

Las comprobaciones de Referer pueden ser falsificadas. Los nonces o tokens de un solo uso son el estándar para proteger contra CSRF. – gravelpot

+0

Asumí tanto. Ahora, en mi sitio, no puede cambiar ** nada ** usando GET, solo POST, el sitio no lo recordará después de cerrar el navegador, y CakePHP ya tiene la generación de "token mágico" para evitar formularios POSS de XSRF . Con todo eso en mente, ¿puedo desactivar esto de forma segura? –

+0

@gravelpot: los encabezados pueden ser falsificados por un atacante, pero de eso no se trata el CSRF, sino de que el navegador del usuario haga las solicitudes desde otro sitio (malicioso) a su (bueno) sitio. En ese caso, no puede falsificar un referente. (Y estoy usando los tokens, y todo en mi sitio está detrás de un muro de inicio de sesión que no "te recuerda") –

4

tener en cuenta que, básicamente, todo el referer_check está haciendo es algo así como:

$pattern = "/^http:\/\/www\.myurl\.com(\/.*)*$/"; 

if(!empty($_SERVER['HTTP_REFERER']) && !preg_match($pattern, $_SERVER['HTTP_REFERER'])) { 
    session_destroy(); 
} 

Es molesto que los PHP construidas en referer_check no aceptarán un conjunto de direcciones URL, pero siempre se puede hacer su propio Eso hace.

Así que para CakePHP, usted podría hacer algo como lo siguiente:

// ADD THIS TO /app/config/config.php 
$config['CustomSecurity'] = array(
    'accept_referers' => array(
     'http://www.my_site.com', 
     'https://www.other_allowed_referer.com', 
    ) 
); 

// ADD THIS TO /app/app_controller.php 

private function referer_check(){ 
    if(!empty($_SERVER['HTTP_REFERER'])) { 
     $accept_referers = Configure::read('CustomSecurity.accept_referers'); 
     $referer_accepted = false; 
     foreach($accept_referers as $referer) { 
     $pattern = '/^'.preg_replace('/(\.|\/)/','\\\$1',$referer).'(\/.*)*$/'; 
     if(preg_match($pattern, $_SERVER['HTTP_REFERER'])) 
      $referer_accepted = true; 
     } 
     if(!$referer_accepted) { 
     $this->Session->destroy(); 
     exit; 
     } 
    }   
} 

Y EN SU FUNCIÓN app_controller::before_filter, LLAMADA:

$this->referer_check(); 

... o algo así de todos modos ... lo siento sobre el formato del código, el área de texto estaba siendo un tard :)

Cuestiones relacionadas