Existe uma função catchall em algum lugar que funcione bem para higienizar a entrada do usuário para injeção de SQL e ataques XSS, enquanto ainda permite certos tipos de tags HTML?
php
security
xss
sql-injection
user-input
Brent
fonte
fonte
select * from users where name='$name'
, então não importa se você usa o PDO ou MySQLi ou MySQL. Você ainda está em perigo. Você deve usar consultas parametrizadas ou, se necessário, usar mecanismos de escape em seus dados, mas isso é muito menos preferível.Respostas:
É um equívoco comum que a entrada do usuário possa ser filtrada. O PHP ainda possui um "recurso" (agora obsoleto), chamado magic-quotes , que se baseia nessa idéia. Não faz sentido. Esqueça a filtragem (ou limpeza, ou como as pessoas chamam).
O que você deve fazer, para evitar problemas, é bastante simples: sempre que você incorpora uma cadeia de caracteres a um código estrangeiro, deve escapar dela, de acordo com as regras desse idioma. Por exemplo, se você incorporar uma string em algum SQL direcionado ao MySQL, deverá escapar da string com a função do MySQL para essa finalidade (
mysqli_real_escape_string
). (Ou, no caso de bancos de dados, usar instruções preparadas é uma abordagem melhor, quando possível.)Outro exemplo é o HTML: se você incorporar cadeias de caracteres na marcação HTML, deverá escapar dela
htmlspecialchars
. Isso significa que cada declaraçãoecho
ouprint
declaração deve ser usadahtmlspecialchars
.Um terceiro exemplo pode ser os comandos do shell: se você deseja incorporar seqüências de caracteres (como argumentos) a comandos externos e chamá-las com
exec
, deve usarescapeshellcmd
eescapeshellarg
.E assim por diante ...
O único caso em que você precisa filtrar ativamente os dados é se você está aceitando entrada pré-formatada. Por exemplo, se você permitir que seus usuários publiquem a marcação HTML, planeja exibir no site. No entanto, é prudente evitar isso a todo custo, pois, independentemente de quão bem você o filtre, sempre será uma falha de segurança em potencial.
fonte
mysql_real_escape_string
está obsoleto. Atualmente, é considerado uma boa prática usar instruções preparadas para impedir a injeção de SQL. Então mude para MySQLi ou PDO.Não tente impedir a injeção de SQL limpando os dados de entrada.
Em vez disso, não permita que dados sejam usados na criação do seu código SQL . Use Instruções Preparadas (ou seja, usando parâmetros em uma consulta de modelo) que usa variáveis ligadas. É a única maneira de garantir a injeção de SQL.
Por favor, consulte o meu site http://bobby-tables.com/ para obter mais informações sobre como evitar a injeção de SQL.
fonte
Não. Você não pode filtrar dados genericamente sem qualquer contexto para o que serve. Às vezes, você deseja aceitar uma consulta SQL como entrada e, às vezes, deseja aceitar HTML como entrada.
Você precisa filtrar a entrada em uma lista de permissões - verifique se os dados correspondem a alguma especificação do que você espera. Então você precisa escapar antes de usá-lo, dependendo do contexto em que o está usando.
O processo de escape de dados para SQL - para impedir a injeção de SQL - é muito diferente do processo de escape de dados para (X) HTML, para impedir o XSS.
fonte
O PHP tem agora as novas funções agradáveis filter_input, que por exemplo o libertam de encontrar 'o melhor regex de e-mail' agora que existe um tipo FILTER_VALIDATE_EMAIL embutido
Minha própria classe de filtro (usa JavaScript para destacar campos defeituosos) pode ser iniciada por uma solicitação ajax ou por uma postagem de formulário normal. (veja o exemplo abaixo)
Obviamente, lembre-se de que você precisa executar sua consulta sql também, dependendo do tipo de banco de dados que você está usando (mysql_real_escape_string () é inútil para um servidor sql, por exemplo). Você provavelmente deseja lidar com isso automaticamente em sua camada de aplicativo apropriada, como um ORM. Além disso, como mencionado acima: para enviar para html use as outras funções dedicadas em php como htmlspecialchars;)
Para permitir realmente a entrada HTML com classes e / ou tags despojadas, dependa de um dos pacotes de validação xss dedicados. NÃO ESCREVA SEUS PRÓPRIOS REGEXES PARA COMPARTILHAR HTML!
fonte
Não, não há.
Em primeiro lugar, a injeção SQL é um problema de filtragem de entrada e o XSS é uma saída que foge da saída - portanto, você nem executaria essas duas operações ao mesmo tempo no ciclo de vida do código.
Regras básicas básicas
mysql_real_escape_string()
)strip_tags()
para filtrar HTML indesejadohtmlspecialchars()
e esteja atento aos segundo e terceiro parâmetros aqui.fonte
Para resolver o problema do XSS, consulte o HTML Purifier . É bastante configurável e tem um histórico decente.
Quanto aos ataques de injeção SQL, verifique a entrada do usuário e execute-a através de mysql_real_escape_string (). Porém, a função não derrota todos os ataques de injeção, portanto, é importante que você verifique os dados antes de jogá-los na cadeia de caracteres da consulta.
Uma solução melhor é usar instruções preparadas. A biblioteca PDO e a extensão mysqli suportam isso.
fonte
O PHP 5.2 introduziu o filter_var função .
Ele suporta uma grande quantidade de filtros SANITIZE, VALIDATE.
http://php.net/manual/en/function.filter-var.php
fonte
Um truque que pode ajudar na circunstância específica em que você tem uma página
/mypage?id=53
e usa o id em uma cláusula WHERE é garantir que o id definitivamente seja um número inteiro, assim:Mas é claro que isso apenas interrompe um ataque específico, portanto, leia todas as outras respostas. (E sim, eu sei que o código acima não é ótimo, mas mostra a defesa específica.)
fonte
$id = (int)$_GET['id']
e$que = sprintf('SELECT ... WHERE id="%d"', $id)
é bom tambémUse versões modernas do MySQL e PHP.
Defina charset explicitamente:
Use conjuntos de caracteres seguros:
Use a função espacializada:
PDO :: quote () - coloca aspas ao redor da string de entrada (se necessário) e escapa caracteres especiais dentro da string de entrada, usando um estilo de aspas apropriado ao driver subjacente:
Declarações Preparadas para DOP : As instruções preparadas contra o MySQLi suportam mais drivers de banco de dados e parâmetros nomeados:
mysql_real_escape_string[obsoleto no PHP 5.5.0, removido no PHP 7.0.0].Verifique se a variável contém o que você está esperando:
Use a Função de Filtro filter_var () - filtra uma variável com um filtro especificado:
filtros mais predefinidos
fonte
O que você está descrevendo aqui são dois problemas separados:
1) A entrada do usuário sempre deve ser considerada ruim.
Usar instruções preparadas ou / e filtrar com mysql_real_escape_string é definitivamente uma obrigação. O PHP também possui filter_input, o que é um bom ponto de partida.
2) Esse é um tópico amplo e depende do contexto dos dados que estão sendo impressos. Para HTML, existem soluções como o htmlpurifier por aí. Como regra geral, sempre escape qualquer coisa que você produz.
Ambos os problemas são grandes demais para serem analisados em uma única postagem, mas há muitas que entram em mais detalhes:
Métodos Saída PHP
Saída PHP mais segura
fonte
Se você estiver usando o PostgreSQL, a entrada do PHP pode ser escapada com pg_escape_string ()
Na documentação ( http://php.net/manual/es/function.pg-escape-string.php ):
fonte
Não existe uma função abrangente, porque há várias preocupações a serem abordadas.
Injeção de SQL - Hoje, geralmente, todo projeto PHP deve usar instruções preparadas por meio de PHP Data Objects (PDO) como uma prática recomendada, evitando erros de aspas perdidas e uma solução completa contra injeção. . É também a maneira mais flexível e segura de acessar seu banco de dados.
Confira o tutorial do PDO (o único apropriado) para praticamente tudo o que você precisa saber sobre o DOP. (Agradecimentos sinceros ao principal colaborador do SO, @YourCommonSense, por este excelente recurso sobre o assunto.)
XSS - higienizar dados a caminho de ...
O Purificador HTML já existe há muito tempo e ainda é atualizado ativamente. Você pode usá-lo para limpar informações maliciosas, enquanto ainda permite uma lista de permissões generosa e configurável. Funciona muito bem com muitos editores WYSIWYG, mas pode ser pesado para alguns casos de uso.
Em outros casos, onde não queremos aceitar HTML / Javascript, achei essa função simples útil (e passou por várias auditorias no XSS):
/* Prevent XSS input */ function sanitizeXSS () { $_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING); $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); $_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST; }
XSS - higienize dados na saída ... a menos que você garanta que os dados foram higienizados adequadamente antes de adicioná-los ao seu banco de dados, será necessário higienizá-los antes de exibi-los para o usuário, podemos aproveitar essas funções úteis do PHP:
echo
ouprint
exibir valores fornecidos pelo usuário, usehtmlspecialchars
, a menos que os dados tenham sido higienizados adequadamente e que sejam permitidos exibir HTML.json_encode
é uma maneira segura de fornecer valores fornecidos pelo usuário, de PHP a JavascriptVocê chama comandos shell externos usando
exec()
ousystem()
functions ou para obacktick
operador? Nesse caso, além do SQL Injection & XSS, você pode ter uma preocupação adicional a tratar, os usuários executando comandos maliciosos no seu servidor . Você precisa usarescapeshellcmd
se quiser escapar de todo o comando OUescapeshellarg
para escapar de argumentos individuais.fonte
mb_encode_numericentity
é discutido nohtmlspecialchars
link # 3 XSSA maneira mais fácil de evitar erros na limpeza de dados de entrada e escape é usar a estrutura PHP como Symfony , Nette etc. ou parte dessa estrutura (mecanismo de modelagem, camada de banco de dados, ORM).
Mecanismos de modelagem como Twig ou Latte têm saída com escape por padrão - você não precisa resolver manualmente se tiver escapado adequadamente da saída, dependendo do contexto (parte HTML ou Javascript da página da web).
O Framework limpa automaticamente as entradas e você não deve usar as variáveis $ _POST, $ _GET ou $ _SESSION diretamente, mas através de mecanismos como roteamento, manipulação de sessões etc.
E para a camada de banco de dados (modelo), existem estruturas ORM como Doctrine ou wrappers em torno do PDO como Nette Database.
Você pode ler mais sobre isso aqui - O que é uma estrutura de software?
fonte
Só queria acrescentar que, no assunto de saída de escape, se você usar o php DOMDocument para fazer sua saída de html, ela escapará automaticamente no contexto certo. Um atributo (value = "") e o texto interno de um <span> não são iguais. Para estar seguro contra o XSS, leia o seguinte: Folha de dicas de prevenção do OWASP XSS
fonte
Você nunca limpa a entrada.
Você sempre limpa a saída.
As transformações que você aplica aos dados para torná-lo seguro para inclusão em uma instrução SQL são completamente diferentes daquelas que você solicita para inclusão em HTML são completamente diferentes daquelas que você solicita para inclusão em Javascript são completamente diferentes daquelas que solicita para inclusão em LDIF. completamente diferentes daqueles que você aplica à inclusão em CSS são completamente diferentes daqueles que você aplica à inclusão em um E-mail ....
Por todos os meios, valide a entrada - decida se você deve aceitá-la para processamento adicional ou se é inaceitável para o usuário. Mas não aplique nenhuma alteração na representação dos dados até que esteja prestes a sair do PHP.
Há muito tempo, alguém tentou inventar um mecanismo único para todos os dados de escape e acabamos com " magic_quotes " que não escapavam adequadamente aos dados de todos os destinos de saída e resultavam em instalações diferentes, exigindo código diferente para funcionar.
fonte
Nunca confie nos dados do usuário.
A
trim()
função remove espaços em branco e outros caracteres predefinidos dos dois lados de uma sequência.A
stripslashes()
função remove barras invertidasA
htmlspecialchars()
função converte alguns caracteres predefinidos em entidades HTML.Os caracteres predefinidos são:
fonte
clean_input
então? Por que você iria querer cortar barras?Existe a extensão do filtro ( howto-link , manual ), que funciona muito bem com todas as variáveis GPC. Não é algo mágico, você ainda precisará usá-lo.
fonte