Pergunta

Especificamente, isso se refere ao uso de um cookie de sessão do cliente para identificar uma sessão no servidor.

A melhor resposta é usar a criptografia SSL/HTTPS para todo o site e você tem a melhor garantia de que nenhum ataque intermediário será capaz de detectar um cookie de sessão de cliente existente?

E talvez a segunda melhor opção seja usar algum tipo de criptografia no próprio valor da sessão que está armazenado no cookie da sessão?

Se um usuário mal-intencionado tiver acesso físico a uma máquina, ele ainda poderá consultar o sistema de arquivos para recuperar um cookie de sessão válido e usá-lo para sequestrar uma sessão?

Foi útil?

Solução

Criptografar o valor da sessão não terá efeito.O cookie de sessão já é um valor arbitrário, criptografá-lo apenas gerará outro valor arbitrário que pode ser detectado.

A única solução real é HTTPS.Se você não quiser usar SSL em todo o site (talvez tenha preocupações com o desempenho), poderá conseguir apenas proteger o SSL das áreas confidenciais.Para fazer isso, primeiro certifique-se de que sua página de login seja HTTPS.Quando um usuário fizer login, defina um cookie seguro (ou seja, o navegador só o transmitirá por meio de um link SSL), além do cookie de sessão normal.Então, quando um usuário visitar uma de suas áreas “sensíveis”, redirecione-o para HTTPS e verifique a presença desse cookie seguro.Um usuário real terá isso, um sequestrador de sessão não.

EDITAR:Esta resposta foi escrita originalmente em 2008.Estamos em 2016 e não há razão para não ter SSL em todo o seu site.Chega de HTTP de texto simples!

Outras dicas

O SSL só ajuda com ataques de detecção.Se um invasor tiver acesso à sua máquina, presumirei que ele também poderá copiar seu cookie seguro.

No mínimo, certifique-se de que os cookies antigos percam o valor depois de um tempo.Mesmo um ataque de sequestro bem-sucedido será frustrado quando o cookie parar de funcionar.Se o usuário tiver um cookie de uma sessão que efetuou login há mais de um mês, faça com que ele digite novamente a senha.Certifique-se de que sempre que um usuário clicar no link "sair" do seu site, o UUID da sessão antiga nunca mais poderá ser usado.

Não tenho certeza se essa ideia funcionará, mas aqui vai:Adicione um número de série ao seu cookie de sessão, talvez uma string como esta:

SessionUUID, número de série, data/hora atual

Criptografe esta string e use-a como cookie de sessão.Altere regularmente o número de série - talvez quando o cookie tiver 5 minutos e emita-o novamente.Você pode até reeditá-lo em cada visualização de página, se desejar.No lado do servidor, mantenha um registro do último número de série emitido para aquela sessão.Se alguém enviar um cookie com o número de série errado, significa que um invasor pode estar usando um cookie que interceptou anteriormente, portanto invalide o UUID da sessão e peça ao usuário para inserir novamente sua senha e, em seguida, emitir novamente um novo cookie.

Lembre-se que seu usuário pode ter mais de um computador, portanto pode ter mais de uma sessão ativa.Não faça algo que os force a fazer login novamente sempre que alternarem entre computadores.

Você já pensou em ler um livro sobre segurança PHP?Altamente recomendado.

Tive muito sucesso com o método a seguir para sites não certificados por SSL.

  1. Desative várias sessões na mesma conta, certificando-se de não verificar isso apenas pelo endereço IP.Em vez disso, verifique pelo token gerado no login que é armazenado com a sessão do usuário no banco de dados, bem como o endereço IP, HTTP_USER_AGENT e assim por diante

  2. O uso de hiperlinks baseados em relação gera um link (por exemplo. http://example.com/secure.php?token=2349df98sdf98a9asdf8fas98df8 ) O link é anexado a uma corda MD5 saltada aleatória do X-byte (tamanho preferido), após o redirecionamento da página, o token gerado aleatoriamente corresponde a uma página solicitada.

    • Ao recarregar, várias verificações são feitas.
    • Endereço IP de origem
    • HTTP_USER_AGENT
    • Token de sessão
    • você entendeu.
  3. Cookie de autenticação de sessão de curta duração.conforme postado acima, um cookie contendo uma string segura, que é uma das referências diretas à validade das sessões, é uma boa ideia.Faça com que ele expire a cada x minutos, reemitindo esse token e sincronizando novamente a sessão com os novos dados.Se houver alguma incompatibilidade nos dados, desconecte o usuário ou peça para ele autenticar novamente sua sessão.

Não sou de forma alguma um especialista no assunto, tive um pouco de experiência neste tópico específico, espero que isso ajude alguém por aí.

// Collect this information on every request
$aip = $_SERVER['REMOTE_ADDR'];
$bip = $_SERVER['HTTP_X_FORWARDED_FOR'];
$agent = $_SERVER['HTTP_USER_AGENT'];
session_start();

// Do this each time the user successfully logs in.
$_SESSION['ident'] = hash("sha256", $aip . $bip . $agent);

// Do this every time the client makes a request to the server, after authenticating
$ident = hash("sha256", $aip . $bip . $agent);
if ($ident != $_SESSION['ident'])
{
    end_session();
    header("Location: login.php");
    // add some fancy pants GET/POST var headers for login.php, that lets you
    // know in the login page to notify the user of why they're being challenged
    // for login again, etc.
}

O que isso faz é capturar informações “contextuais” sobre a sessão do usuário, informações que não devem mudar durante a vida de uma única sessão.Um usuário não estará em um computador nos EUA e na China ao mesmo tempo, certo?Portanto, se o endereço IP mudar repentinamente na mesma sessão, isso implica fortemente uma tentativa de sequestro de sessão, então você protege a sessão encerrando-a e forçando o usuário a se autenticar novamente.Isso frustra a tentativa de hack, o invasor também é forçado a fazer login em vez de obter acesso à sessão.Notifique o usuário sobre a tentativa (aumente um pouco), e vola, usuário ligeiramente irritado + informado e sua sessão/informações estão protegidas.

Incluímos o User Agent e o X-FORWARDED-FOR para fazer o nosso melhor para capturar a exclusividade de uma sessão para sistemas atrás de proxies/redes.Você pode usar mais informações do que isso, fique à vontade para ser criativo.

Não é 100%, mas é bastante eficaz.

Há mais que você pode fazer para proteger as sessões, expirá-las, quando um usuário sai de um site e volta, forçá-lo a fazer login novamente, talvez.Você pode detectar a saída e o retorno de um usuário capturando um HTTP_REFERER em branco (o domínio foi digitado na barra de URL) ou verificar se o valor no HTTP_REFERER é igual ao seu domínio ou não (o usuário clicou em um link externo/criado para acessar seu site).

Expire as sessões, não deixe que elas permaneçam válidas indefinidamente.

Não confie em cookies, eles podem ser roubados, é um dos vetores de ataque para sequestro de sessão.

Experimente o protocolo Secure Cookie descrito em esse artigo de Liu, Kovacs, Huang e Gouda:

Conforme declarado no documento:

Um protocolo de cookie seguro que é executado entre um cliente e um servidor precisa fornecer os quatro serviços a seguir:autenticação, confidencialidade, integridade e anti-replay.

Quanto à facilidade de implantação:

Em termos de eficiência, nosso protocolo não envolve nenhuma pesquisa de banco de dados ou criptografia pública.Em termos de implantabilidade, nosso protocolo pode ser facilmente implantado em um servidor da web existente e não requer nenhuma alteração na especificação da Internet Cookie.

Resumidamente:é seguro, leve e funciona muito bem para mim.

Não há como evitar 100% o sequestro de sessão, mas com alguma abordagem podemos reduzir o tempo para um invasor sequestrar a sessão.

Método para evitar o sequestro de sessão:

1 - utilize sempre sessão com certificado SSL;

2 - enviar cookie de sessão apenas com httponly definido como verdadeiro (evitar que o javascript acesse o cookie de sessão)

2 - use o ID de regeneração da sessão no login e logout (nota:não use a regeneração de sessão em cada solicitação porque se você tiver uma solicitação ajax consecutiva, terá a chance de criar várias sessões.)

3 - defina um tempo limite de sessão

4 - armazene o agente do usuário do navegador em uma variável $_SESSION e compare com $_SERVER['HTTP_USER_AGENT'] a cada solicitação

5 - defina um cookie token e defina o tempo de expiração desse cookie como 0 (até que o navegador seja fechado).Gere novamente o valor do cookie para cada solicitação (para solicitação ajax, não gere novamente o cookie do token).EX:

    //set a token cookie if one not exist
    if(!isset($_COOKIE['user_token'])){
                    //generate a random string for cookie value
        $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));

        //set a session variable with that random string
        $_SESSION['user_token'] = $cookie_token;
        //set cookie with rand value
        setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
    }

    //set a sesison variable with request of www.example.com
    if(!isset($_SESSION['request'])){
        $_SESSION['request'] = -1;
    }
    //increment $_SESSION['request'] with 1 for each request at www.example.com
    $_SESSION['request']++;

    //verify if $_SESSION['user_token'] it's equal with $_COOKIE['user_token'] only for $_SESSION['request'] > 0
    if($_SESSION['request'] > 0){

        // if it's equal then regenerete value of token cookie if not then destroy_session
        if($_SESSION['user_token'] === $_COOKIE['user_token']){
            $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));

            $_SESSION['user_token'] = $cookie_token;

            setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
        }else{
            //code for session_destroy
        }

    }

            //prevent session hijaking with browser user agent
    if(!isset($_SESSION['user_agent'])){
        $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
    }

    if($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']){
      die('session hijaking - user agent');
    }

observação:Não regenere o biscoito de token com o Ajax Pedido Nota:o código acima é um exemplo.observação:se os usuários saírem, o token do cookie deverá ser destruído, assim como a sessão

6 - não é uma boa abordagem usar o IP do usuário para evitar o sequestro de sessão porque o IP de alguns usuários muda a cada solicitação.QUE AFETAM USUÁRIOS VÁLIDOS

7 - pessoalmente eu armazeno os dados da sessão em banco de dados, cabe a você decidir qual método adotar

Se você encontrar um erro em minha abordagem, corrija-me.Se você tiver mais maneiras de evitar o hyjaking de sessão, por favor me diga.

Certifique-se de não usar números inteiros incrementais para IDs de sessão.É muito melhor usar um GUID ou alguma outra sequência de caracteres longa gerada aleatoriamente.

Há muitas maneiras de criar proteção contra sequestro de sessão, mas todas elas reduzem a satisfação do usuário ou não são seguras.

  • Verificações de IP e/ou X-FORWARDED-FOR.Eles funcionam e são bastante seguros ...mas imagine a dor dos usuários.Eles chegam a um escritório com WiFi, obtêm um novo endereço IP e perdem a sessão.Tenho que fazer login novamente.

  • Verificações do agente do usuário.Assim como acima, uma nova versão do navegador foi lançada e você perde uma sessão.Além disso, eles são realmente fáceis de “hackear”.É trivial para hackers enviarem strings UA falsas.

  • Token de armazenamento local.Ao fazer logon, gere um token, armazene-o no armazenamento do navegador e armazene-o em um cookie criptografado (criptografado no lado do servidor).Isso não tem efeitos colaterais para o usuário (o localStorage persiste durante as atualizações do navegador).Não é tão seguro - é apenas segurança através da obscuridade.Além disso, você pode adicionar alguma lógica (criptografia/descriptografia) ao JS para obscurecê-lo ainda mais.

  • Reemissão de cookies.Esta é provavelmente a maneira certa de fazer isso.O truque é permitir que apenas um cliente use um cookie por vez.Portanto, o usuário ativo terá o cookie reemitido a cada hora ou menos.O cookie antigo será invalidado se um novo for emitido.Hacks ainda são possíveis, mas muito mais difíceis de fazer - tanto o hacker quanto o usuário válido terão o acesso rejeitado.

Vamos considerar que durante a fase de login o cliente e o servidor podem concordar com um valor secreto de salt.Depois disso, o servidor fornece um valor de contagem a cada atualização e espera que o cliente responda com o hash do (sal secreto + contagem).O potencial sequestrador não tem como obter esse valor secreto de sal e, portanto, não pode gerar o próximo hash.

AFAIK o objeto de sessão não está acessível no cliente, pois está armazenado no servidor web.No entanto, o ID da sessão é armazenado como um cookie e permite que o servidor web rastreie a sessão do usuário.

Para evitar o sequestro de sessão usando o ID da sessão, você pode armazenar uma string hash dentro do objeto de sessão, feita usando uma combinação de dois atributos, endereço remoto e porta remota, que podem ser acessados ​​no servidor web dentro do objeto de solicitação.Esses atributos vinculam a sessão do usuário ao navegador onde o usuário efetuou login.

Se o usuário fizer login em outro navegador ou no modo de navegação anônima no mesmo sistema, o endereço IP permanecerá o mesmo, mas a porta será diferente.Portanto, quando o aplicativo for acessado, o usuário receberá um ID de sessão diferente pelo servidor web.

Abaixo está o código que implementei e testei copiando o ID da sessão de uma sessão para outra.Funciona muito bem.Se houver uma lacuna, deixe-me saber como você a simulou.

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    HttpSession session = request.getSession();
    String sessionKey = (String) session.getAttribute("sessionkey");
    String remoteAddr = request.getRemoteAddr();
    int remotePort = request.getRemotePort();
    String sha256Hex = DigestUtils.sha256Hex(remoteAddr + remotePort);
    if (sessionKey == null || sessionKey.isEmpty()) {
        session.setAttribute("sessionkey", sha256Hex);
        // save mapping to memory to track which user attempted
        Application.userSessionMap.put(sha256Hex, remoteAddr + remotePort);
    } else if (!sha256Hex.equals(sessionKey)) {
        session.invalidate();
        response.getWriter().append(Application.userSessionMap.get(sessionKey));
        response.getWriter().append(" attempted to hijack session id ").append(request.getRequestedSessionId()); 
        response.getWriter().append("of user ").append(Application.userSessionMap.get(sha256Hex));
        return;
    }
    response.getWriter().append("Valid Session\n");
}

Usei o algoritmo SHA-2 para fazer o hash do valor usando o exemplo dado em Hashing SHA-256 e baeldung

Fico na expectativa dos seus comentários.

Para reduzir o risco você também pode associar o IP de origem à sessão.Dessa forma, um invasor precisa estar na mesma rede privada para poder usar a sessão.

Verificar os cabeçalhos dos referenciadores também pode ser uma opção, mas eles são falsificados mais facilmente.

Proteger por:

$ip=$_SERVER['REMOTE_ADDER'];
$_SESSEION['ip']=$ip;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top