A segurança da informação é uma preocupação central no mundo da tecnologia e é, muitas vezes, um tópico negligenciado em sistemas de gerenciamento de banco de dados e aplicações web. Um dos ataques mais comuns e perigosos que podem comprometer a segurança de um sistema é a injeção de SQL. Neste artigo, exploraremos em profundidade o que é a injeção de SQL, como ela funciona e, mais importante, por que ela ocorre, tomando como exemplo um código PHP vulnerável.
O que é SQL Injection?
A injeção de SQL é uma vulnerabilidade de segurança que ocorre quando um invasor manipula as entradas de um sistema para inserir comandos SQL maliciosos em consultas SQL legítimas. Isso pode permitir que o invasor execute comandos não autorizados em um banco de dados, comprometendo dados confidenciais, modificando ou excluindo registros e até mesmo assumindo o controle do sistema. Para entender como a injeção de SQL funciona, vamos analisar um exemplo prático em PHP.
Exemplo de Código Vulnerável em PHP + HTML Forms
<?php
ini_set("display_errors",1);
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$nc = mysqli_connect('localhost','root','1111');
mysqli_select_db($nc,'injection');
$usuario = $_POST['usuario'];
$senha = $_POST['senha'];
$sql = "SELECT * FROM login WHERE usuario = '$usuario' AND senha='$senha'";
$query = mysqli_query($nc, $sql);
if(mysqli_num_rows($query)==1) {
header("location:admin.html");
}
else {
echo "Usuário ou senha inválidos";
}
}
?>
HTML Forms:
<!DOCTYPE html>
<html>
<head>
<title>SQL Injection</title>
</head>
<body>
<form action="index.php" method="POST">
<h1>Login - Vulnerável</h1><br>
Usuário:<br>
<input type="text"
name="usuario"<br><br>
Senha:<br>
<input type="text"
name="senha"<br><br>
<input type="submit" value="Login">
</Form>
</body>
Como Funciona a Injeção de SQL?
A vulnerabilidade neste código reside na forma como as variáveis $usuario e $senha são incorporadas diretamente na consulta SQL, sem validação adequada. Isso cria uma oportunidade para um atacante explorar a injeção de SQL. Se o invasor fornecer entradas maliciosas, como usuario com o valor ' OR '1'='1 e senha vazia, a consulta SQL resultante se parecerá com:
SELECT * FROM login WHERE usuario = '' OR '1'='1' AND senha='';
O `' OR '1'='1` é sempre verdadeiro, o que significa que o invasor pode enganar o sistema e obter acesso, mesmo sem a senha correta. Isso ocorre porque o código não está filtrando ou escapando as entradas do usuário adequadamente, permitindo que comandos SQL maliciosos sejam injetados na consulta.
Por que a Injeção de SQL Acontece?
A injeção de SQL ocorre principalmente devido a duas razões principais:
1. Falta de Validação de Entradas:
Os desenvolvedores muitas vezes não validam ou sanitizam adequadamente as entradas do usuário. Isso permite que os invasores insiram comandos SQL diretamente nas entradas do aplicativo.
2. Concatenação de Strings SQL:
A concatenação direta de entradas do usuário com strings SQL sem escapar ou usar parâmetros preparados cria uma abertura para a injeção de SQL.
Exemplo de tratamento parametrizado (PDO)
No exemplo abaixo, podemos observar que o código está utilizando uma nova forma de parametrização dos valores que são recebidos pelo usuário, validando o tipo de entrada/campo, antes de permitir o envio de strings do usuário para a aplicação
$sql = "SELECT * FROM login WHERE usuario=:usuario AND senha=:senha;";
$stmt = $conn->prepare( $sql );
$stmt-> bindParam( ':usuario', $usuario );
$stmt-> bindParam( ':senha', $senha );
$stmt->execute();
$result = $stmt->fetchAll();
if (count($result)) {
header("location: admin2.php");
}
else {
throw new Error($stmt->errorInfo());
}
}
?>
stmt = $conn->prepare( $sql );: Nesta linha, você está preparando uma consulta SQL para ser executada. $conn provavelmente é um objeto de conexão PDO que representa uma conexão com o banco de dados. $sql é a consulta SQL que você deseja preparar. Isso é feito para evitar a injeção de SQL, pois o PDO cuidará da sanitização e da execução segura da consulta.
stmt->bindParam( ':usuario', $usuario );: Aqui, você está vinculando um parâmetro nomeado :usuario na consulta SQL à variável $usuario. Isso significa que, quando a consulta for executada, o valor de $usuario será substituído no lugar de :usuario. Isso é útil para passar valores dinâmicos para a consulta sem se preocupar com a injeção de SQL.
stmt->bindParam( ':senha', $senha );: Da mesma forma, você está vinculando um parâmetro nomeado :senha à variável $senha. Isso permite que você substitua o valor de $senha na consulta.
stmt->execute();: Aqui, você está executando a consulta preparada. Isso significa que a consulta será enviada ao banco de dados com os valores de :usuario e :senha substituídos pelos valores em $usuario e $senha. A consulta será executada pelo banco de dados.
result = $stmt->fetchAll();: Depois que a consulta é executada com sucesso, você está pegando todas as linhas de resultados e armazenando-as em $result. Isso geralmente é usado quando você espera receber vários resultados da consulta, como ao buscar várias linhas de um banco de dados.
Em resumo, esse código PHP está preparando e executando uma consulta SQL segura usando PDO. Ele vincula os valores das variáveis $usuario e $senha à consulta, garantindo que eles sejam tratados de maneira segura e evitando vulnerabilidades de injeção de SQL.
Em tempo, PDO significa PHP Data Object e é uma extensão do PHP que fornece uma camada de abstração de acesso a banco de dados, nesse caso, SQL.
Conclusão
A injeção de SQL é uma ameaça séria à segurança de sistemas de banco de dados e aplicações web. Para evitá-la, os desenvolvedores devem validar e escapar adequadamente as entradas do usuário, além de utilizar parâmetros preparados em vez de concatenar strings SQL. Conscientização sobre segurança e práticas de desenvolvimento seguro são cruciais para proteger sistemas contra esse tipo de ataque. Aprender com exemplos como o apresentado neste artigo é um passo importante na direção certa para melhorar a segurança dos sistemas.
Referência Bibliográfica
LUCENA, Alan Rodrigo Ferreira de; LEITE, Renan Dias. Gestão de Vulnerabilidade em Aplicações WEB: Exploração de SQL Injection. 2019. Monografia (Graduação em Gestão da Tecnologia da Informação) - Tecnológico, Faculdade de Ciências de Timbaúba (FACET), Timbaúba, 2019. DOI 10.29327/41302367. Disponível em:
Gestão de Vulnerabilidade em Aplicações WEB: Exploração de SQL Injection | TCC - Graduação | Even3 Publicações