Injeção de SQL
Injeção SQL
A injeção de SQL é uma técnica de injeção de código que pode destruir seu banco de dados.
A injeção de SQL é uma das técnicas de hacking mais comuns na web.
A injeção de SQL é a colocação de código malicioso em instruções SQL, por meio de entrada de página da web.
SQL em páginas da Web
A injeção de SQL geralmente ocorre quando você solicita a entrada de um usuário, como seu nome de usuário/id de usuário e, em vez de um nome/id, o usuário fornece uma instrução SQL que você executará inadvertidamente em seu banco de dados.
Veja o exemplo a seguir que cria uma
SELECT
instrução adicionando uma variável (txtUserId) a uma string de seleção. A variável é buscada na entrada do usuário (getRequestString):
Exemplo
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
O restante deste capítulo descreve os perigos potenciais de usar a entrada do usuário em instruções SQL.
SQL Injection Baseado em 1=1 é Sempre Verdadeiro
Observe o exemplo acima novamente. O objetivo original do código era criar uma instrução SQL para selecionar um usuário, com um determinado ID de usuário.
Se não houver nada que impeça um usuário de inserir uma entrada "errada", o usuário pode inserir alguma entrada "inteligente" como esta:
ID do usuário:
Então, a instrução SQL ficará assim:
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
O SQL acima é válido e retornará TODAS as linhas da tabela "Usuários", pois OR 1=1 é sempre TRUE.
O exemplo acima parece perigoso? E se a tabela "Usuários" contiver nomes e senhas?
A instrução SQL acima é muito parecida com esta:
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1;
Um hacker pode obter acesso a todos os nomes de usuário e senhas em um banco de dados, simplesmente inserindo 105 OR 1=1 no campo de entrada.
SQL Injection com base em ""="" é sempre verdadeiro
Aqui está um exemplo de login de usuário em um site:
Nome do usuário:
Senha:
Exemplo
uName = getRequestString("username");
uPass = getRequestString("userpassword");
sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass +
'"'
Resultado
SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass"
Um hacker pode obter acesso a nomes de usuário e senhas em um banco de dados simplesmente inserindo " OR ""=" na caixa de texto de nome de usuário ou senha:
Nome do usuário:
Senha:
O código no servidor criará uma instrução SQL válida como esta:
Resultado
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
O SQL acima é válido e retornará todas as linhas da tabela "Users", pois OR ""="" é sempre TRUE.
Injeção de SQL com base em instruções SQL em lote
A maioria dos bancos de dados oferece suporte à instrução SQL em lote.
Um lote de instruções SQL é um grupo de duas ou mais instruções SQL, separadas por ponto e vírgula.
A instrução SQL abaixo retornará todas as linhas da tabela "Usuários" e excluirá a tabela "Fornecedores".
Exemplo
SELECT * FROM Users; DROP TABLE Suppliers
Observe o seguinte exemplo:
Exemplo
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
E a seguinte entrada:
ID do usuário:
A instrução SQL válida ficaria assim:
Resultado
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers;
Usar parâmetros SQL para proteção
Para proteger um site da injeção de SQL, você pode usar parâmetros SQL.
Parâmetros SQL são valores que são adicionados a uma consulta SQL em tempo de execução, de forma controlada.
Exemplo de Razor ASP.NET
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
Observe que os parâmetros são representados na instrução SQL por um marcador @.
O mecanismo SQL verifica cada parâmetro para garantir que esteja correto para sua coluna e seja tratado literalmente, e não como parte do SQL a ser executado.
Outro exemplo
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);
Exemplos
Os exemplos a seguir mostram como criar consultas parametrizadas em algumas linguagens comuns da Web.
SELECIONE A DECLARAÇÃO NO ASP.NET:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserId);
command.ExecuteReader();
INSERIR NA DECLARAÇÃO NO ASP.NET:
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();
INSERIR NA DECLARAÇÃO EM PHP:
$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();