Entendendo SQL Injection
Este artigo tem como objetivo explorar metodicamente a vulnerabilidade SQL Injection, demonstrando como ela ocorre e qual a causa dessa vulnerabilidade ser tão recorrente até os dias atuais.
Introdução
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.
HTML Forms:
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.
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.
$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.
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.
______________________________________________________________________
Inscreva-se no meu Canal: https://www.youtube.com/@LinuxDicasPro
Repositório GitHub do Canal: https://github.com/LinuxDicasPro
Grupo do Telegram: https://t.me/LinuxDicasPro
Meu GitHub Pessoal: https://github.com/mxnt10