SQL Injection em ADVPL: Como me proteger?

Aloha!

Sou o Arthur Fücher e nesse meu primeiro post venho falar de um assunto bem crítico e que possui uma forma bem tranquila de ser tratado: SQL Injection.

O que é SQL Injection?

SQL Injection, ou Injeção SQL, é uma falha onde é possível injetar código SQL dentro de uma consulta que o sistema executa no Banco de Dados.

Para entender melhor vamos imaginar o seguinte cenário:

Temos uma aplicação com uma tela simples de login: Usuário, Senha e um botão de Login. Ao clicar no botão a aplicação pega o valor das variáveis de user e password e monta a consulta para executar no banco da seguinte maneira:

"SELECT * 
 FROM users 
 WHERE username = '"+ user +"' AND password = '"+ password + "'"

Supondo que a pessoa digitou meu_usuario e a senha 123, teremos a seguinte consulta:

SELECT * 
FROM users 
WHERE username = 'meu_usuario' AND password = '123'

Agora vamos supor que uma pessoa má intencionada digite no lugar campo de user o seguinte valor: ‘ OR 1=1–, parece um texto sem sentido certo?? Mas vamos ver como que ficaria na nossa consulta:

SELECT * FROM users WHERE username = '' OR 1=1--' AND password = '123'

 

Veja que foi injetado na consulta um OR 1 =1, com isso ela sempre retornará resultados e mesmo sem validar usuário e senha o login será feito! :O

Prepared Statement

Para evitar essa injeção podemos utilizar o conceito de Prepared Statement, onde montamos uma consulta pré-definida, e depois injetamos somente os parâmetros que são alteráveis nela. Com isso os parâmetros são tratados individualmente, evitando a injeção.

Para identificar os parâmetros, substituímos seus valores pelo caractere ‘?’.

Para exemplificar vou mostrar como ficaria nossa consulta:

SELECT * FROM users WHERE username=? AND password=?

Para se beneficiar do Prepared Statement em AdvPL basta utilizar a classe FWPreparedStatement

//Inicializa as variáveis
oStatement := FWPreparedStatement():New()
cQuery := "SELECT * FROM users WHERE username=? AND password=?"
//Define a consulta e os parâmetros
oStatement:SetQuery(cQuery)
oStatement:SetString(1,cUser)
oStatement:SetString(1,cPassword)
//Recupera a consulta já com os parâmetros injetados
cFinalQuery := oStatement:GetFixQuery()

Se passarmos os mesmos parâmetros do exemplo, teremos o seguinte resultado:

SELECT * FROM users WHERE username=''' OR 1=1--' AND password='123'

Obs.: Este é um exemplo bem simples, sabemos que por exemplo senhas não devem ser gravadas diretas no banco. O intuito é apenas demonstrar o uso de Prepared Statement para evitar SQL Injection.


Espero que esse post tenha sido útil!

Até breve!

 

 

Anúncios