it-swarm-pt.tech

Quais são as melhores práticas para evitar ataques xss em um site PHP

Eu tenho PHP configurado para que aspas mágicas estejam ativadas e registradores globais desativados.

Faço o possível para sempre chamar htmlentities () para qualquer coisa que eu esteja produzindo, derivada da entrada do usuário.

Ocasionalmente, também busco no meu banco de dados coisas comuns usadas no xss anexadas, como ...

<script

O que mais devo fazer e como posso ter certeza de que as coisas que estou tentando fazer estão sempre concluídas.

65
Rik Heywood

A entrada de escape não é o melhor que você pode fazer para obter uma prevenção XSS bem-sucedida. Também a saída deve ser escapada. Se você usa o mecanismo de modelo do Smarty, pode usar |escape:'htmlall' modificador para converter todos os caracteres confidenciais em entidades HTML (eu uso o próprio |e modificador que é alias ao acima).

Minha abordagem à segurança de entrada/saída é:

  • armazenar entrada do usuário não modificada (sem escape de HTML na entrada, somente escape com reconhecimento de banco de dados feito por meio de instruções preparadas pelo DOP)
  • escape na saída, dependendo do formato de saída usado (por exemplo, HTML e JSON precisam de regras de escape diferentes)
58
Michał Rudnicki

Sou da opinião de que não se deve escapar de nada durante a entrada, apenas na saída. Desde (na maioria das vezes), você não pode assumir que sabe para onde esses dados estão indo. Por exemplo, se você possui um formulário que aceita dados que posteriormente aparecem em um email enviado, você precisa de uma saída diferente (caso contrário, um usuário mal-intencionado pode reescrever seus cabeçalhos de email).

Em outras palavras, você só pode escapar no último momento em que os dados estão "saindo" do seu aplicativo:

  • Item da lista
  • Escreva para arquivo XML, escape para XML
  • Grave no DB, escape (para esse DBMS específico)
  • Escreva e-mail, escape para e-mails
  • etc

Para ir curto:

  1. Você não sabe para onde seus dados estão indo
  2. Os dados podem acabar em mais de um lugar, necessitando de mecanismos de escape diferentes, MAS NÃO AMBOS
  3. Dados escapados para o alvo errado não são realmente agradáveis. (Por exemplo, receba um e-mail com o assunto "Vá para a barra do Tommy".)

O esp # 3 ocorrerá se você escapar dados na camada de entrada (ou precisar retirá-los novamente, etc).

PS: Seguirei o conselho de não usar magic_quotes, são pura maldade!

18
Jilles

Existem várias maneiras de fazer o XSS (consulte http://ha.ckers.org/xss.html ) e é muito difícil de entender.

Pessoalmente, delegar isso na estrutura atual que estou usando (Code Igniter, por exemplo). Embora não seja perfeito, pode pegar mais do que minhas rotinas feitas à mão.

12
Christian Studer

Esta é uma grande pergunta.

Primeiro, não escape o texto na entrada, exceto para torná-lo seguro para armazenamento (como ser colocado em um banco de dados). A razão para isso é que você deseja manter o que foi inserido, para poder apresentá-lo contextualmente de diferentes maneiras e lugares. Fazer alterações aqui pode comprometer sua apresentação posterior.

Quando você vai apresentar seus dados, filtre o que não deveria estar lá. Por exemplo, se não houver um motivo para o javascript estar lá, procure-o e remova-o. Uma maneira fácil de fazer isso é usar a função strip_tags e apresentar apenas as tags html que você está permitindo.

Em seguida, pegue o que você tem e passe-o para htmlentities ou htmlspecialchars para alterar o que há nos caracteres ASCII. Faça isso com base no contexto e no que você deseja divulgar.

Eu também sugeriria desativar Magic Quotes. Foi removido de PHP 6 e é considerado uma má prática para usá-lo. Detalhes em http://us3.php.net/magic_quotes

Para mais detalhes, consulte http://ha.ckers.org/xss.html

Esta não é uma resposta completa, mas espero que seja suficiente para ajudar você a começar.

10
Matt Farina

faço o possível para sempre chamar htmlentities () para qualquer coisa que eu esteja produzindo, derivada da entrada do usuário.

.

See Joel's essay on Making Code Look Wrong for help with this

7
Mason

Eu confio em PHPTAL para isso.

Ao contrário do Smarty e do PHP simples, ele escapa de toda a saída por padrão. Esta é uma grande vitória para a segurança, porque seu site não se tornará vurnelable se você esquecer htmlspecialchars() ou |escape algum lugar.

O XSS é um ataque específico do HTML; portanto, a saída HTML é o lugar certo para evitá-lo. Você não deve tentar pré-filtrar os dados no banco de dados, porque pode ser necessário enviar dados para outro meio que não aceite HTML, mas que possui seus próprios riscos.

4
Kornel

Biblioteca de modelos. Ou, pelo menos, é isso que as bibliotecas de modelos devem fazer. Para impedir o XSS , toda a saída deve ser codificada. Esta não é a tarefa da lógica principal de aplicativo/controle, ela deve ser tratada apenas pelos métodos de saída.

Se você espalhar htmlentities () em todo o seu código, o design geral estará errado. E como você sugere, você pode perder um ou dois pontos. É por isso que a única solução é a rigorosa codificação html -> quando os vars de saída são gravados em um fluxo html/xml.

Infelizmente, a maioria das bibliotecas de modelos php adiciona apenas sua própria sintaxe, mas não se preocupa com a codificação de saída, localização, validação de html ou qualquer coisa importante. Talvez alguém conhece uma biblioteca de modelos adequada para php?

4
user319490

Se você está preocupado com ataques XSS, codificar suas seqüências de saída para HTML é a solução. Se você se lembrar de codificar cada caractere de saída para o formato HTML, não há como executar um ataque XSS bem-sucedido.

Leia mais: Higienizando dados do usuário: como e onde fazê-lo

2
Niyaz

Pessoalmente, eu desabilitaria magic_quotes. No PHP5 +, ele é desativado por padrão e é melhor codificar como se não estivesse presente, pois não escapa a tudo e será removido do PHP6.

Em seguida, dependendo do tipo de dados do usuário que você estiver filtrando, será ditado o que fazer em seguida, por exemplo. se for apenas texto, por exemplo um nome, strip_tags(trim(stripslashes())); ou, para verificar intervalos, use expressões regulares.

Se você espera um certo intervalo de valores, crie uma matriz dos valores válidos e permita apenas esses valores (in_array($userData, array(...))).

Se você estiver verificando números, use is_numeric para aplicar números inteiros ou converter para um tipo específico, isso deve impedir que as pessoas tentem enviar seqüências de caracteres em vez disso.

Se você possui o PHP5.2 +, considere olhar para filter () e usar essa extensão que pode filtrar vários tipos de dados, incluindo endereços de email. A documentação não é particularmente boa, mas está melhorando.

Se você precisa lidar com HTML, deve considerar algo como Filtro de Entrada PHP ou Purificador de HTML . O Purificador de HTML também validará o HTML para conformidade. Não tenho certeza se o Filtro de entrada ainda está sendo desenvolvido. Ambos permitem definir um conjunto de tags que podem ser usadas e quais atributos são permitidos.

O que você decidir, lembre-se sempre, nunca confie em nada que esteja entrando no seu script PHP de um usuário (incluindo você!)).

2
Dave

Acho que o uso dessa função ajuda a eliminar muitos possíveis ataques xss: http://www.codebelay.com/killxss.phps

2
barce

As "citações mágicas" são um remédio paliativo para algumas das piores falhas do XSS, que funcionam escapando a tudo da entrada, algo que está errado no design. O único caso em que alguém gostaria de usá-lo é quando você absolutamente precisa usar um aplicativo existente PHP conhecido por ser escrito descuidadamente com relação ao XSS. (Nesse caso, você está com um problema sério mesmo com “aspas mágicas”.) Ao desenvolver seu próprio aplicativo, desative as “aspas mágicas” e siga as práticas seguras para XSS.

XSS, uma vulnerabilidade de script entre sites, ocorre quando um aplicativo inclui seqüências de caracteres de fontes externas (entrada do usuário, buscadas em outros sites etc.) em seu [X] HTML, CSS, ECMAscript ou outra saída analisada pelo navegador sem escape adequado, esperando que caracteres especiais como menor que (em [X] HTML), aspas simples ou duplas (ECMAscript) nunca serão exibidos. A solução adequada é sempre escapar seqüências de caracteres de acordo com as regras da linguagem de saída: usando entidades no [X] HTML, barras invertidas no ECMAscript etc.

Como pode ser difícil acompanhar o que não é confiável e deve ser evitado, é uma boa ideia sempre escapar de tudo o que é uma "sequência de texto" em oposição a "texto com marcação" em uma linguagem como HTML. Alguns ambientes de programação facilitam a introdução de vários tipos de string incompatíveis: "string" (texto normal), "string HTML" (marcação HTML) e assim por diante. Dessa forma, uma conversão implícita direta de "string" para "HTML string" seria impossível, e a única maneira de uma string se tornar uma marcação HTML é passando por uma função de escape.

O “Register Global”, apesar de desativá-lo definitivamente é uma boa ideia, lida com um problema completamente diferente do XSS.

2
Alexey Feldgendler

Escapar de toda a entrada do usuário é suficiente para a maioria dos sites. Verifique também se os IDs da sessão não terminam no URL, para que não possam ser roubados do link Referer para outro site. Além disso, se você permitir que seus usuários enviem links, verifique se não javascript: links de protocolo são permitidos; estes executariam um script assim que o usuário clicar no link.

2
Konrad Rudolph

Todas essas respostas são ótimas, mas, fundamentalmente, a solução para o XSS será parar de gerar documentos HTML por manipulação de strings.

A entrada de filtragem é sempre uma boa ideia para qualquer aplicativo.

Escapar da saída usando htmlentities () e amigos deve funcionar desde que seja usado corretamente, mas esse é o equivalente em HTML da criação de uma consulta SQL concatenando as strings com mysql_real_escape_string ($ var) - deve funcionar, mas menos coisas podem validar seu trabalho , por assim dizer, em comparação com uma abordagem como o uso de consultas parametrizadas.

A solução a longo prazo deve ser para aplicativos construírem a página internamente, talvez usando uma interface padrão como o DOM e, em seguida, usar uma biblioteca (como libxml) para lidar com a serialização em XHTML/HTML/etc. Obviamente, estamos muito longe de ser popular e rápido o suficiente, mas, enquanto isso, precisamos criar nossos documentos HTML por meio de operações de string, e isso é inerentemente mais arriscado.

2
Daniel Papasian
  • Não confie na entrada do usuário
  • Escapar de toda a saída de texto livre
  • Não use magic_quotes; veja se há uma variante específica do DBMS ou use o DOP
  • Considere usar cookies somente HTTP, sempre que possível, para evitar que qualquer script mal-intencionado possa seqüestrar uma sessão
1
Rob

Você deve pelo menos validar todos os dados que entram no banco de dados. E tente validar todos os dados que saem do banco de dados também.

mysql_real_escape_string é bom para evitar a injeção de SQL, mas o XSS é mais complicado. Você deve preg_match, stip_tags ou htmlentities sempre que possível!

1
Abeon

O melhor método atual para impedir o XSS em um aplicativo PHP é o HTML Purifier (http://htmlpurifier.org/).) Uma desvantagem menor é que é uma biblioteca bastante grande e é melhor usada com um cache de código operacional como o APC. Você o usaria em qualquer lugar em que o conteúdo não confiável fosse enviado para a tela. É muito mais detalhado que htmlentities, htmlspecialchars, filter_input, filter_var, filter_var, strip_tags etc.

1
Night Owl

Faça de você os cookies de sessão (ou todos os cookies) que você usa HttpOnly. A maioria dos navegadores ocultará o valor do cookie do JavaScript nesse caso. O usuário ainda pode copiar manualmente os cookies, mas isso ajuda a impedir o acesso direto ao script. O StackOverflow teve esse problema durante o beta.

Esta não é uma solução, apenas mais um tijolo na parede

1
basszero

Acho que a melhor maneira é usar uma classe que permita vincular seu código para que você nunca precise se preocupar com a fuga manual de seus dados.

0
Darren22

Use uma biblioteca de higienização de entrada do usuário existente para limpar todos entrada do usuário. A menos que você faça um esforço de lote nele, a implementação você mesmo nunca funcionará tão bem.

0
dbr