Segurança de Sessão PHP

125

Quais são algumas diretrizes para manter a segurança da sessão responsável com o PHP? Há informações em toda a web e já é hora de tudo chegar em um só lugar!

saint_groceon
fonte

Respostas:

88

Existem algumas coisas a fazer para manter sua sessão segura:

  1. Use SSL ao autenticar usuários ou executar operações confidenciais.
  2. Gere novamente a identificação da sessão sempre que o nível de segurança for alterado (como o login). Você pode gerar novamente a identificação da sessão a cada solicitação, se desejar.
  3. As sessões expiram
  4. Não use globals de registro
  5. Armazene detalhes de autenticação no servidor. Ou seja, não envie detalhes como nome de usuário no cookie.
  6. Verifique o $_SERVER['HTTP_USER_AGENT']. Isso adiciona uma pequena barreira ao seqüestro de sessões. Você também pode verificar o endereço IP. Mas isso causa problemas para os usuários que alteram o endereço IP devido ao balanceamento de carga em várias conexões com a Internet, etc. (que é o caso em nosso ambiente aqui).
  7. Bloqueie o acesso às sessões no sistema de arquivos ou use manipulação de sessão personalizada
  8. Para operações confidenciais, considere exigir que os usuários conectados forneçam seus detalhes de autenticação novamente
grom
fonte
15
Usar SSL apenas para algumas operações não é suficiente, a menos que você tenha sessões separadas para tráfego criptografado e não criptografado. Se você usar uma sessão única por HTTPS e HTTP, o invasor a roubará na primeira solicitação que não seja HTTPS.
Kornel
6
-1 o agente do usuário é trivial para falsificar. O que você está descrevendo desperdiça código e não é um sistema de segurança.
rook
24
@ The Rook, pode ser uma barreira trivial (o invasor pode capturar o user agent de uma vítima usando seu próprio site) e confia na segurança através da obscuridade, mas ainda é uma barreira extra. Se o HTTP do agente do usuário fosse alterado durante o uso da sessão, seria extremamente suspeito e provavelmente um ataque. Eu nunca disse que você pode usá-lo sozinho. Se você combiná-lo com outras técnicas, você terá um site muito mais seguro.
quer
5
@grom Eu acho que é como colocar um pedaço de fita adesiva em toda a sua porta e dizendo que vai impedir as pessoas de quebrar em.
torre
8
Se você estiver verificando o agente do usuário, bloqueará todas as solicitações dos usuários do IE8 quando eles alternarem o modo de compatibilidade. Veja a diversão que tive ao rastrear esse problema em meu próprio código: serverfault.com/questions/200018/http-302-problem-on-ie7 . Estou retirando o agente do usuário, porque é uma coisa tão trivial falsificar, como outros já disseram.
bestattendance
15

Uma diretriz é chamar session_regenerate_id toda vez que o nível de segurança de uma sessão for alterado. Isso ajuda a impedir o seqüestro de sessões.

saint_groceon
fonte
11

Meus dois (ou mais) centavos:

  • Não confies em ninguém
  • Entrada de filtro, saída de escape (cookie, dados da sessão também são sua entrada)
  • Evite o XSS (mantenha seu HTML bem formado, consulte PHPTAL ou HTMLPurifier )
  • Defesa em profundidade
  • Não exponha dados

Há um pequeno mas bom livro sobre este tópico: Essential PHP Security, de Chris Shiflett .

Segurança essencial do PHP http://shiflett.org/images/essential-php-security-small.png

Na home page do livro, você encontrará alguns exemplos de código interessantes e exemplos de capítulos.

Você pode usar a técnica mencionada acima (IP e UserAgent), descrita aqui: Como evitar o roubo de identidade

leva
fonte
+1 para prevenção de XSS. Sem isso, é impossível proteger contra o CSRF e, portanto, alguém pode "montar" a sessão sem obter o ID da sessão.
Kornel
11

Eu acho que um dos principais problemas (que está sendo tratado no PHP 6) é o register_globals. Neste momento, um dos métodos convencionais usado para evitar register_globalsé usar os $_REQUEST, $_GETou $_POSTmatrizes.

A maneira "correta" de fazê-lo (a partir da versão 5.2, embora seja um pouco problemática, mas estável a partir da 6, que será lançada em breve) é através de filtros .

Então, em vez de:

$username = $_POST["username"];

você faria:

$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);

ou mesmo apenas:

$username = filter_input(INPUT_POST, 'username');
cmcculloh
fonte
2
Isso não tem nenhuma relação com a questão.
The Pixel Developer
5
Realmente? Então, por que na resposta aceita eles mencionam não usar globals de registro? No que diz respeito à maioria dos desenvolvedores comuns, não seria, o registro global e o tratamento de variáveis ​​se enquadrariam nas "sessões", mesmo que não seja tecnicamente parte do objeto "sessão"?
Cmcculloh 18/08/09
9
Concordo que isso não responde totalmente à pergunta, mas é definitivamente parte da resposta à pergunta. Novamente, isso exibe um marcador na resposta aceita: "Não use registradores globais". Isso diz o que fazer em seu lugar.
precisa saber é o seguinte
5

Usar o endereço IP não é realmente a melhor ideia na minha experiência. Por exemplo; meu escritório tem dois endereços IP que são usados ​​dependendo da carga e constantemente enfrentamos problemas usando endereços IP.

Em vez disso, optei por armazenar as sessões em um banco de dados separado para os domínios em meus servidores. Dessa forma, ninguém no sistema de arquivos tem acesso a essas informações da sessão. Isso foi realmente útil com o phpBB antes da versão 3.0 (eles já corrigiram isso), mas ainda é uma boa idéia, eu acho.

Eric Lamb
fonte
3

Isso é bastante trivial e óbvio, mas certifique-se de sessão_destruir após cada uso. Isso pode ser difícil de implementar se o usuário não fizer logout explicitamente, portanto, um timer pode ser configurado para fazer isso.

Aqui está um bom tutorial sobre setTimer () e clearTimer ().

helloandre
fonte
3

O principal problema com as sessões e segurança do PHP (além do seqüestro de sessão) vem com o ambiente em que você está. Por padrão, o PHP armazena os dados da sessão em um arquivo no diretório temporário do sistema operacional. Sem nenhum pensamento ou planejamento especial, este é um diretório legível mundialmente, portanto todas as informações da sua sessão são públicas para qualquer pessoa com acesso ao servidor.

Quanto à manutenção de sessões em vários servidores. Nesse ponto, seria melhor alternar o PHP para sessões manipuladas pelo usuário, onde ele chama suas funções fornecidas para CRUD (criar, ler, atualizar, excluir) os dados da sessão. Nesse ponto, você pode armazenar as informações da sessão em um banco de dados ou em uma solução semelhante ao memcache, para que todos os servidores de aplicativos tenham acesso aos dados.

Armazenar suas próprias sessões também pode ser vantajoso se você estiver em um servidor compartilhado, pois ele permitirá armazená-lo no banco de dados, que muitas vezes você tem mais controle sobre o sistema de arquivos.

John Downey
fonte
3

Eu configurei minhas sessões assim -

na página de login:

$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR']);

(frase definida em uma página de configuração)

depois, no cabeçalho do restante do site:

session_start();
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR'])) {       
    session_destroy();
    header('Location: http://website login page/');
    exit();     
}
Chade
fonte
3

php.ini

session.cookie_httponly = 1
change session name from default PHPSESSID

eq Apache add header:

X-XSS-Protection    1
user956584
fonte
httpd.conf -> <FilesMatch "\. (php | phtml | aspx | htm | html) $"> Conjunto de cabeçalho X-XSS-Protection "1" </FilesMatch>
user956584
Esteja ciente de que X-XSS-Protectionnão é realmente útil. De fato, o próprio algoritmo de proteção poderia ser explorado, tornando-o pior do que antes.
Pacerier 13/07/12
2

Eu verificaria o IP e o User Agent para ver se eles mudam

if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
    || $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
    //Something fishy is going on here?
}
Teifion
fonte
5
O IP pode mudar legitimamente se o usuário estiver atrás do farm de proxy com balanceamento de carga.
Kornel
2
E user_agent pode mudar sempre que um usuário atualiza seu navegador.
Scotts scotts
3
@scotts Concordo com a parte do IP, mas, para a atualização do navegador, você definiria a sessão quando eles fizerem login, para que eu não veja como eles atualizariam o navegador sem criar uma nova sessão depois de fazer o login novamente.
JasonDavis
Acredito que o user_agent também pode mudar ao alternar entre o modo compatível no IE8. Também é muito fácil de falsificar.
Sim, mas e os usuários que tinham IP eq GSM estático e são alterados a cada meia hora. Portanto, o IP armazenado no Session + nome do host, WHEN IP! = REMOTE_ADDR, verifica o host e compara hostanmes eq. 12.12.12.holand.nl-> quando é holand.nl == verdadeiro. Mas alguns anfitrião teve hostname baseada em IP seguida, é necessário comparar mascarar 88.99.XX.XX
user956584
2

Se você usar session_set_save_handler (), poderá definir seu próprio manipulador de sessões. Por exemplo, você pode armazenar suas sessões no banco de dados. Consulte os comentários do php.net para exemplos de um manipulador de sessões de banco de dados.

As sessões de banco de dados também são boas se você tiver vários servidores, caso contrário, se estiver usando sessões baseadas em arquivos, será necessário garantir que cada servidor da Web tenha acesso ao mesmo sistema de arquivos para ler / gravar as sessões.

ejunker
fonte
2

Você precisa ter certeza de que os dados da sessão estão seguros. Olhando para o seu php.ini ou usando o phpinfo (), você pode encontrar as configurações da sessão. _session.save_path_ informa onde eles são salvos.

Verifique a permissão da pasta e de seus pais. Não deve ser público (/ tmp) ou estar acessível por outros sites em seu servidor compartilhado.

Supondo que você ainda deseja usar a sessão php, você pode configurar o php para usar outra pasta alterando _session.save_path_ ou salvar os dados no banco de dados alterando _session.save_handler_.

Você pode ser capaz de definir _session.save_path_ no seu php.ini (alguns provedores de permitir que ele) ou para apache + mod_php, em um arquivo .htaccess na pasta raiz do site: php_value session.save_path "/home/example.com/html/session". Você também pode configurá-lo em tempo de execução com _session_save_path () _.

Verifique o tutorial de Chris Shiflett ou Zend_Session_SaveHandler_DbTable para definir um manipulador de sessão alternativo.

Dinoboff
fonte