Ao invés de focar em como evitar que a identificação da sessão seja capturada, vou focar em como evitar que a captura da id da sessão traga problemas. O objetivo deste artigo é complicar ao máximo a personificação, lembrando que cada complicação que aplicamos ao nosso código aumenta a segurança e frusta o atacante. Para fazer isso, vamos ver os passos necessários para roubar uma sessão. Em cada um dos casos, vamos assumir que a identificação da sessão foi comprometida.
Com um mecanismo simples de sessão, apenas uma identificação da sessão que seja válida é necessária. Neste caso, vamos melhorar nosso código adicionando mais verificações através das requisições HTTP.
Lembre-se: Não é recomendável utilizar dados do nível do protocolo TCP/IP (como o endereço IP), pois este protocolo não foi feito para acomodar atividades no nível HTTP. Um único usuário pode ter diversos endereços IP's a cada requisição, assim como múltiplos usuários podem ter o mesmo IP (um proxy, por exemplo).
Vamos lembrar uma típica requisição HTTP:
GET / HTTP/1.1 Host: uidroot.com User-Agent: Mozilla/5.0 Gecko/20061010 Firefox/2.0 Accept: text/xml, image/png, image/jpeg, image/gif, */* Cookie: PHPSESSID=1234
Apenas o cabeçalho Host é requerido pelo HTTP/1.1, logo, não é ideal confiar nos outros dados. Entretanto, a única coisa que precisamos é checar a consistência, porque queremos complicar a personificação sem afetar os usuários legítimos, não é mesmo?!
Vamos imaginar que depois da requisição passada, vêm a seguinte requisição, como um User-Agent diferente:
GET / HTTP/1.1 Host: uidroot.com User-Agent: Mozilla Compatible (MSIE 7) Accept: text/xml, image/png, image/jpeg, image/gif, */* Cookie: PHPSESSID=1234
Veja que o cookie é o mesmo, mas devemos considerar esta requisição como vindo do mesmo usuário?!
É MUITO improvável que o usuário mudaria o User-Agent entre requisições, certo?! Vamos modificar nosso mecanismo de sessão para fazer uma nova verificação:
<?php
session_start();
if (isset($_SESSION['HTTP_USER_AGENT']))
{
if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT']))
{
// O user_agent da requisição antiga não bate com o atual
// Neste ponto, é importante fazer novamente a autenticação do usuário
// pedindo seu login/senha
exit;
}
}
else
{
$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
}
?>O código acima obriga o atacante a usar não apenas uma identificação de sessão válida, mas também o user-agent correto. Isto complica um pouco a vida do atacante e deixa a sessão um pouco mais segura.
Será que podemos melhorar o código?! Leve em consideração que o método mais comum de obter os cookies é explorando falhas em um browser vulnerável, como o Internet Explorer. Esses exploits geralmente envolvem em redirecionar a vítima ao site do atacante, logo, o atacante saberá qual o user-agent da vítima e poderá obtê-lo corretamente e passar pela nossa verificação de user-agent.
Bom, imaginem se, além do md5 do user-agent, poderíamos passar mais alguns pedaços de informação. Isto dificultaria e muito o nosso potencial atacante. Temos que manter uma boa lógica para evitar que usuários legítimos sejam afetados por verificações que sejam feitas de maneira incorreta. Nosso objetivo é diminuir problemas e não aumentá-los. Vamos escrever o seguinte código:
Página identifica.php
<?php
session_start();
// Retira as variáveis da sessão.
$_SESSION = array();
//Destrói o cookie da sessão
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
// Destrói a sessão
session_destroy();
//Inicia uma nova sessão
session_start();
$codigo = $_SERVER['HTTP_USER_AGENT'];
$codigo .= 'É com você Adeildo';
$digital = md5($codigo);
echo '<form action="consulta.php?chk=' . $digital . '" method="post">';
//Seu formulario de autenticação
?>Página consulta.php
<?php
//Existe $_GET['chk']?
if(!isset($_GET['chk'])){
header("Location:identifica.php");
die();
}
$codigo = $_SERVER['HTTP_USER_AGENT'];
$codigo .= 'É com você Adeildo';
$digital = md5($codigo);
//O $_GET['chk'] bate com a id digital?
if ($digital != $_GET['chk']){
header("Location:identifica.php");
die();
}
//sessão é válida
session_start();
//Processa o resto do código
?>Este código funciona assim:
O usuário normal faz login na página identifica.php e vai para consulta.php
O atacante, de posse da id da sessão e user_agent, acessa direto a página consulta.php, mas ele (assim esperamos) não tem o $_GET['chk'], ou seja, a identificação virtual gerada unicamente na página de login identifica.php. O código adicional "É com você Adeildo" não deve ser divulgado, pois ele garante que o nosso md5() gerado seja único. Em outras palavras, se o atacante tentar passar só o md5 do user-agent, ele não conseguirá acesso, o md5 deve ser do user-agent + $codigo secreto e não apenas do user-agent.
Existem ainda, muitas outras maneiras de melhorar o sistema de sessões, mas isso depende da sua criatividade e do seu sistema de sessões em si. Não se esqueça que o alvo são os atacantes e não os usuários legítimos.
Ao pegar um exploit de sessão, nunca acuse o potencial atacante, mas sim solicite a senha novamente. Se você pegar um usuário legítimo e acusá-lo de algo que ele não fez, pode apostar, você terá que, além de arrumar o sistema de sessão, dar uma boa explicação ao usuário (ou ao seu chefe).
Autor: Rodolfo Andrade

Entrar
Cadastre-se
Ajuda
Responder


Quote

