01/01/2024
SQL Injection é um ataque que permite a invasores modificar operações de banco de dados através de um aplicativo. Isso pode resultar em acesso indevido e manipulação de dados, incluindo a exclusão de tabelas ou alteração de senhas de usuários.
Aqui está um exemplo de código PHP vulnerável a SQL Injection, com um parâmetro de URL:
// Exemplo de código PHP vulnerável a SQL Injection
// Recebendo 'id' da URL
$id = $_GET['id'];
// Montagem insegura da consulta
$query = "SELECT * FROM users WHERE id = $id";
// Execução da consulta...
Este código é vulnerável porque usa diretamente um dado externo ('id' da URL) na consulta SQL. Por exemplo, se o parâmetro 'id' da URL for alteradp para id=0; DROP TABLE users;
, a consulta se tornará SELECT * FROM users WHERE id = 0; DROP TABLE users;
, resultando na exclusão da tabela 'users' e perda de todos os dados.
Utilizar PDO (PHP Data Objects) com named parameters é uma maneira eficiente de proteger seu código PHP contra SQL Injection. Vamos aprimorar nosso código inicial com o uso de PDO:
// Protegendo o código com PDO
// Estabelecendo conexão PDO
$pdo = new PDO('mysql:host=localhost;dbname=banco', 'usuario', 'senha');
// Garantindo que 'id' seja um número inteiro
$id = (int) $_GET['id'];
// Preparando a consulta com named parameter
$query = "SELECT * FROM users WHERE id = :id";
$stmt = $pdo->prepare($query);
// Executando a consulta com um parâmetro seguro
$stmt->execute(['id' => $id]);
// Código para manipulação dos resultados...
Ao converter o 'id' para um inteiro, garantimos que apenas valores numéricos sejam usados na consulta, adicionando uma camada extra de segurança.
Embora o MySQLi não permita a vinculação de parâmetros diretamente no execute como o PDO, ele ainda é uma ferramenta segura contra SQL Injection. Vamos ver como usar o MySQLi com segurança:
// Protegendo o código com MySQLi
// Conectando ao banco de dados com MySQLi
$mysqli = new mysqli('localhost', 'usuario', 'senha', 'banco');
// Garantindo que 'id' seja um número inteiro
$id = (int) $_GET['id'];
// Preparando a consulta
$query = "SELECT * FROM users WHERE id = ?";
$stmt = $mysqli->prepare($query);
// Vinculando parâmetro 'id' como inteiro
$stmt->bind_param('i', $id);
// Executando a consulta segura
$stmt->execute();
// Código para manipulação dos resultados...
Usando o `bind_param`, vinculamos o 'id' de forma segura à consulta, prevenindo a injeção de SQL.
Para sistemas legados que ainda utilizam a biblioteca mysql, é importante manter a segurança. Veja um exemplo de código seguro:
// Protegendo sistemas legados com
$conexao = mysql_connect('localhost', 'usuario', 'senha');
mysql_select_db('banco', $conexao);
// Usando escape diretamente na consulta SQL
$id = (int) $_GET['id'];
$query = "SELECT * FROM users WHERE id = " . mysql_real_escape_string($id, $conexao);
$resultado = mysql_query($query);
// Código para manipulação dos resultados...
mysql_close($conexao);
Mesmo em sistemas legados, é possível manter a segurança, garantindo que os parâmetros sejam tratados de forma segura e utilizando validações.
As funções filter_var
e filter_input
do PHP são ferramentas essenciais para validar e filtrar dados de entrada. Elas oferecem diversos filtros e validações, garantindo a segurança e o formato adequado dos dados recebidos.
filter_var
é usada para filtrar e validar dados já existentes em variáveis. Por exemplo, para validar um e-mail:
// Validando um e-mail com filter_var
$email = $_POST['email'];
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
// E-mail válido
// Processamento adicional...
} else {
// E-mail inválido
// Tratamento de erro...
}
E para filtrar um número inteiro:
// Filtrando um inteiro com filter_var
$idade = $_POST['idade'];
$idadeFiltrada = filter_var($idade, FILTER_SANITIZE_NUMBER_INT);
// Utilizar $idadeFiltrada em operações seguras...
filter_input
é usada para coletar e validar dados diretamente da fonte de entrada (como GET e POST), oferecendo uma abordagem mais segura. Por exemplo, para obter e validar um número inteiro via GET:
// Validando um inteiro com filter_input
$idade = filter_input(INPUT_GET, 'idade', FILTER_VALIDATE_INT);
if ($idade !== false) {
// Idade válida ou zero
// Processamento adicional...
} else {
// Idade inválida
// Tratamento de erro...
}
Da mesma forma, para validar um e-mail recebido via POST:
// Validando um e-mail com filter_input
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ($email !== false) {
// E-mail válido ou em branco
// Processamento adicional...
} else {
// E-mail inválido
// Tratamento de erro...
}
Conclusão: filter_var
e filter_input
são ferramentas poderosas para garantir a integridade e a segurança dos dados manipulados em aplicações PHP. Utilizar a comparação estrita com `false` é essencial para diferenciar entre uma entrada inválida e uma entrada em branco ou zero.
Proteger seu código PHP contra SQL Injection é fundamental para garantir a segurança de suas aplicações. Neste artigo, abordamos técnicas para evitar essa vulnerabilidade, incluindo o uso de PDO, MySQLi e proteção em sistemas legados com mysql.
Lembre-se sempre de validar e tratar os dados de entrada, evitando concatenação direta em consultas SQL. A segurança de suas aplicações depende dessas práticas, evitando potenciais ataques e prejuízos.