Eu entendo que você NUNCA deve confiar na entrada do usuário de um formulário, principalmente devido à chance de injeção de SQL.
No entanto, isso também se aplica a um formulário em que a única entrada é proveniente de uma (s) lista (s) suspensa (s) (veja abaixo)?
Estou salvando o $_POST['size']
em uma sessão que é então usada em todo o site para consultar os vários bancos de dados (com uma mysqli
consulta Select) e qualquer injeção de SQL definitivamente os prejudicaria (possivelmente eliminaria).
Não há área para entrada do usuário digitada para consultar os bancos de dados, apenas dropdown (s).
<form action="welcome.php" method="post">
<select name="size">
<option value="All">Select Size</option>
<option value="Large">Large</option>
<option value="Medium">Medium</option>
<option value="Small">Small</option>
</select>
<input type="submit">
</form>
php
mysql
mysqli
sql-injection
Farrapos
fonte
fonte
<select>
entrada. Na verdade, até mesmo um usuário ligeiramente técnico pode adicionar opções adicionais usando o console do navegador. se você mantiver uma lista de permissões de array de valores disponíveis e comparar a entrada com ela, pode mitigar isso (e deve, porque evita valores indesejados)Respostas:
Você pode fazer algo tão simples quanto o exemplo a seguir para garantir que o tamanho postado seja o que você espera.
Então use mysqli_ * se você estiver usando uma versão do php> = 5.3.0 que você deveria estar, para salvar seu resultado. Se usado corretamente, ajudará na injeção de sql.
fonte
mysqli_real_escape_string
. Também escape adequadamente os valores ao gerá-los (por exemplo, use htmlspecialchars () em um documento HTML).in_array
paratrue
para comparação estrita. Não tenho certeza do que pode dar errado, mas a comparação solta é muito peculiar.Sim, você precisa se proteger contra isso.
Deixe-me mostrar por quê, usando o console de desenvolvedor do Firefox:
Se você não limpar esses dados, seu banco de dados será destruído. (Esta pode não ser uma instrução SQL totalmente válida, mas espero ter entendido bem.)
Só porque você limitou as opções disponíveis em sua lista suspensa , não significa que você limitou os dados que posso enviar ao seu servidor.
Se você tentou restringir isso ainda mais usando o comportamento em sua página, minhas opções incluem desativar esse comportamento ou apenas escrever uma solicitação HTTP personalizada para seu servidor que imita o envio deste formulário de qualquer maneira. Existe uma ferramenta chamada curl usada exatamente para isso, e acho que o comando para enviar essa injeção de SQL de qualquer maneira seria mais ou menos assim:
(Este pode não ser um comando curl totalmente válido, mas, novamente, espero ter entendido bem.)
Então, vou reiterar:
NUNCA confie na entrada do usuário. SEMPRE se proteja.
Não presuma que nenhuma entrada do usuário seja segura. É potencialmente inseguro, mesmo se chegar por algum meio diferente de um formulário. Nada disso é confiável o suficiente para deixar de se proteger da injeção de SQL.
fonte
curl
. SEMPRE limpe a entrada do lado do servidor !curl
. As pessoas não entendem que você pode enviar uma solicitação HTTP de qualquer lugar para qualquer lugar usando qualquer formato e passando quaisquer valores, cabe ao servidor verificar se a solicitação é válida antes de processá-la.Como esta pergunta foi marcada com injeção SQL, aqui está uma resposta sobre este tipo específico de ataque:
Como você foi informado nos comentários, você deve usar instruções preparadas para cada consulta envolvendo qualquer dado variável, sem exceções .
Independentemente de qualquer coisa HTML!
É essencial entender que as consultas SQL devem ser formatadas corretamente, independentemente de quaisquer fatores externos, seja uma entrada HTML ou qualquer outra coisa.
Embora você possa usar a lista de desbloqueio sugerida em outras respostas para o propósito de validação de entrada, ela não deve afetar nenhuma ação relacionada a SQL - elas devem permanecer as mesmas, não importa se você validou a entrada HTML ou não. Isso significa que você ainda deve usar instruções preparadas ao adicionar quaisquer variáveis à consulta.
Aqui você pode encontrar uma explicação completa, por que as instruções preparadas são obrigatórias e como usá-las adequadamente e onde não são aplicáveis e o que fazer nesse caso: O Guia do Mochileiro para proteção de injeção de SQL
Além disso, esta pergunta foi marcada com mysqli. Principalmente por acidente, presumo, mas de qualquer forma, devo avisá-lo que mysqli bruto não é uma substituição adequada para as antigas funções mysq_ * . Simplesmente porque, se usado no estilo antigo, não adicionará segurança alguma. Embora seu suporte para as instruções preparadas seja doloroso e problemático, a tal ponto que o usuário médio de PHP é simplesmente incapaz de empreendê-los. Assim, se nenhum ORM ou algum tipo de biblioteca de abstração for opção, então o PDO é sua única escolha.
fonte
random
?Sim.
Qualquer um pode falsificar qualquer coisa pelos valores que realmente são enviados -
PORTANTO, para validar menus suspensos, você pode apenas verificar se o valor com o qual está trabalhando estava no menu suspenso - algo como este seria a melhor (mais sensatamente paranóica) maneira:
fonte
Uma maneira de se proteger contra usuários que alteram seus menus suspensos usando o console é usar apenas valores inteiros neles. Em seguida, você pode validar se o valor POST contém um inteiro e usar uma matriz para convertê-lo em texto quando necessário. Por exemplo:
Então você pode usar
$size
em sua consulta com o conhecimento de que ela conterá apenasFALSE
um número inteiro.fonte
filter_input
senão uma verificação no lado do servidor? Ninguém pode postar nada, exceto um número inteiro.filter_input
parte também para a validação, caso contrário, é tão útil quanto um bule de chocolate por segurança.As outras respostas já cobrem o que você precisa saber. Mas talvez ajude a esclarecer um pouco mais:
Existem DUAS COISAS que você precisa fazer:
1. Valide os dados do formulário.
Como a resposta de Jonathan Hobbs mostra muito claramente, a escolha do elemento html para a entrada do formulário não oferece nenhuma filtragem confiável para você.
A validação geralmente é feita de uma forma que não altera os dados, mas que mostra o formulário novamente, com os campos marcados como "Corrija isso".
A maioria das estruturas e CMSs tem construtores de formulários que o ajudam nessa tarefa. E não apenas isso, eles também ajudam contra o CSRF (ou "XSRF"), que é outra forma de ataque.
2. Sanitize / Escape variáveis em instruções SQL.
.. ou deixe que as declarações preparadas façam o trabalho por você.
Se você construir uma instrução (My) SQL com quaisquer variáveis, fornecidas pelo usuário ou não, você precisa escapar e citar essas variáveis.
Geralmente, qualquer variável inserida em uma instrução MySQL deve ser uma string ou algo que o PHP pode ser transformado de forma confiável em uma string que o MySQL pode digerir. Por exemplo, números.
Para strings, você precisa escolher um dos vários métodos para escapar da string, ou seja, substituir quaisquer caracteres que teriam efeitos colaterais no MySQL.
Se estiver lidando com um número, você pode omitir o escape e as aspas (é por isso que as instruções preparadas permitem especificar um tipo).
É importante ressaltar que você escapa das variáveis para a instrução SQL, e NÃO para o próprio banco de dados . O banco de dados armazenará a string original, mas a instrução precisa de uma versão com escape.
O que acontece se você omitir um desses?
Se você não usar a validação de formulário , mas limpar sua entrada SQL, poderá ver todos os tipos de coisas ruins acontecendo, mas não verá injeção de SQL! (*)
Primeiro, ele pode levar seu aplicativo a um estado que você não planejou. Por exemplo, se você deseja calcular a idade média de todos os usuários, mas um usuário deu "aljkdfaqer" para a idade, seu cálculo falhará.
Em segundo lugar, pode haver todos os tipos de outros ataques de injeção que você precisa considerar: Por exemplo, a entrada do usuário pode conter javascript ou outras coisas.
Ainda pode haver problemas com o banco de dados: por exemplo, se um campo (coluna da tabela do banco de dados) estiver limitado a 255 caracteres e a string for maior do que isso. Ou se o campo aceitar apenas números e você tentar salvar uma string não numérica. Mas isso não é "injeção", é apenas "travar o aplicativo".
Mas, mesmo se você tiver um campo de texto livre onde permite qualquer entrada sem nenhuma validação, você ainda pode salvar isso no banco de dados assim, se você escapar apropriadamente quando for para uma instrução de banco de dados. O problema surge quando você deseja usar esta string em algum lugar.
(*) ou isso seria algo realmente exótico.
Se você não escapar variáveis para instruções SQL , mas validar a entrada do formulário, ainda poderá ver coisas ruins acontecendo.
Em primeiro lugar, você corre o risco de que, ao salvar os dados no banco de dados e carregá-los novamente, não sejam mais os mesmos dados, "perdidos na tradução".
Em segundo lugar, isso pode resultar em instruções SQL inválidas e, portanto, travar seu aplicativo. Por exemplo, se qualquer variável contém uma aspa ou caractere de aspas duplas, dependendo do tipo de aspas que você usa, você obterá uma instrução MySQL inválida.
Em terceiro lugar, ele ainda pode causar injeção de SQL.
Se sua entrada de usuário de formulários já estiver filtrada / validada, a injeção SQl intencional pode se tornar menos provável, SE sua entrada for reduzida a uma lista de opções codificada ou se for restrita a números. Mas qualquer entrada de texto livre pode ser usada para injeção de SQL, se você não escapar adequadamente das variáveis nas instruções SQL.
E mesmo que você não tenha nenhuma entrada de formulário, você ainda pode ter strings de todos os tipos de fontes: lidas do sistema de arquivos, copiadas da Internet, etc. Ninguém pode garantir que essas strings sejam seguras.
fonte
Seu navegador não "sabe" que está recebendo uma página do php, tudo o que vê é html. E a camada http sabe ainda menos do que isso. Você precisa ser capaz de lidar com quase qualquer tipo de entrada que possa cruzar a camada http (felizmente, para a maioria das entradas, o php já apresentará um erro). Se você está tentando evitar que solicitações maliciosas bagunçam seu banco de dados, então você precisa assumir que o cara do outro lado sabe o que está fazendo, e que ele não está limitado ao que você pode ver em seu navegador em circunstâncias normais ( sem mencionar o que você pode mexer com as ferramentas de desenvolvedor de um navegador). Então, sim, você precisa atender a qualquer entrada de sua lista suspensa, mas para a maioria das entradas, você pode fornecer um erro.
fonte
O fato de você ter restringido o usuário a usar apenas valores de uma determinada lista suspensa é irrelevante. Um usuário técnico pode capturar a solicitação http enviada ao seu servidor antes que ela saia da rede, alterá-la usando uma ferramenta como um servidor proxy local e, em seguida, continuar seu caminho. Usando a solicitação alterada, eles podem enviar valores de parâmetro que não sejam aqueles que você especificou na lista suspensa. Os desenvolvedores devem ter a mentalidade de que as restrições do cliente geralmente não fazem sentido, pois qualquer coisa em um cliente pode ser alterada. A validação do servidor é necessária em cada ponto em que os dados do cliente entram. Os invasores contam com a ingenuidade dos desenvolvedores apenas neste aspecto.
fonte
É melhor usar uma consulta parametrizada para evitar a injeção de SQL. Nesse caso, a aparência da consulta seria esta:
Quando você fornece uma consulta como a acima com texto cuja integridade não foi verificada (a entrada não é validada no servidor) e contém código de injeção SQL, ela será tratada corretamente. Em outras palavras, a solicitação resultará em algo assim acontecendo na camada do banco de dados:
Isso simplesmente selecionará 0 resultados conforme retorna, o que tornará a consulta ineficaz em realmente causar danos ao banco de dados sem a necessidade de uma lista de permissões, verificação ou outras técnicas. Observe que um programador responsável fará a segurança em camadas e frequentemente fará a validação, além de parametrizar as consultas. No entanto, há muito poucos motivos para não parametrizar suas consultas de uma perspectiva de desempenho e a segurança adicionada por esta prática é um bom motivo para se familiarizar com as consultas parametrizadas.
fonte
O que quer que seja enviado do seu formulário chega ao servidor como texto através dos fios. Não há nada que impeça ninguém de criar um bot para imitar o cliente ou digitá-lo em um terminal, se quiserem. Nunca presuma que, por ter programado o cliente, ele agirá como você pensa que fará. Isso é realmente fácil de falsificar.
Exemplo do que pode e vai acontecer quando você confia no cliente.
fonte
Um hacker pode ignorar o navegador completamente, incluindo a verificação de formulário Javascript, enviando uma solicitação usando Telnet. Claro, ele vai olhar o código da sua página html para obter os nomes dos campos que precisa usar, mas a partir de então é 'vale tudo' para ele. Portanto, você deve verificar todos os valores enviados no servidor como se eles não tivessem origem na sua página html.
fonte