MySQL
DICA: Se estiver logado no mysql via terminal e quiser utilizar o terminal do SO com as mesmas autenticações do MySQL, basta utilizar o comando: \! sh
. Caso o MySQL estiver sendo executado como root, isso acaba se tornando um fácil PrivEsc.
Obtendo Informações Sobre o MySQL
QUERY
DESCRIÇÃO
SELECT @@hostname
Nome do host
SELECT @@version
Versão do MySQL e do SO
SELECT version()
Versão do MySQL e do SO
SELECT @@datdir
Local onde o MySQL está instalado
SELECT system_user()
Usuário do sistema
SELECT current_user()
Usuário que está executando os comandos
SELECT user()
Usuário que está executando os comandos
SELECT user, password, host FROM mysql.user
Vendo todos os usuarios do DB
SELECT database()
Nome do Banco de Dados está sendo utilizado
SHOW VARIABLES
Mostra as variáveis do MySQL
Instalando MariaDB + Criação de Usuário + Acesso Externo
Instale o MariaDB (Altere a versão caso precise)
Acesse o Banco de Dados
Altere a senha do usuário root
Crie um novo database com uma tabela
Crie um novo usuário do MariaDB
Dê permissão ao novo usuário para determinada IP
Libere acesso na porta 3306 através do firewall
Edita o arquivo de configuração (/etc/mysql/mariadb.conf.d/50-server.cnf
), e altere a linha #bind-address = 127.0.0.1
para bind-address = 0.0.0.0
. Se preferir, utilize o IP da interface de rede ao invés de 0.0.0.0
.
Reinicie o MariaDB e já está pronto para acessar.
Order By
Com o comando order by
, podemos saber quantas colunas o banco de dados está retornando
Nos dois exemplos acima, basta ir aumentando o número do order by
até dar erro. Quando der erro, significa que o valor anterior é a quantidade de colunas retornada na query
Union
Agora que já sabemos a quantidade de colunas utilizando o comando order by
, vamos fazer um union
OBS.: Também podemos utilizar o union
para saber a quantidade de colunas baseada em erros, assim como no order by
.
NOTA: Isso funciona para o MySQL, a metodologia é diferente para outros bancos de dados, os valores 1,2,3,...
devem ser alterados para null,null,null...
para o banco de dados que precisa do mesmo tipo de valor nos 2 lados (SELECT inicial e SELECT do UNION). No Oracle é obrigado a usar o FROM, quando o SELECT for utilizado.
Limit
As vezes podemos usar algum payload de forma que a query nos retorne todos os dados, porém nosso amigo programador limitou esse resultado para pegar apenas 1 registro, usando a linguagem de programação da aplicação ao invés de usar o limit
do MySQL. Para esse cenário, devemos utilizar a seguinte técnica para nos trazer apenas 1 registro de cada vez, porém percorrendo todas as linhas de uma determinar tabela, enviando uma requisição para cada registro.
SQL Blind
Verificando tamanho do nome dos Databases
Altere a quantidade no final do payload abaixo, até encontrar o valor correto.
IMPORTANTE: Estamos utilizando o LIMIT 1,1
, isso significa que só irá retornar o primeiro database. Depois de achar o valor correto, filtre pelo segundo database, modificando para LIMIT 2,1
e assim sucessivamente. Utilize isso para dar continuidade nas verificações abaixo.
Buscando nomes de Databases
Podemos realizar um injection para verificar se existe algum database no banco de dados que comece uma determinada letra. Tente a letra "a", caso seja false, tente a letra "b", e assim sucessivamente,a até encontrar uma letra que retorne true.
Depois de encontrar a primeira letra do nome do database, vamos procurar pela segunda letra e assim por diante, até mapearmos o nome do database. Atente-se que os databases também pode conter números, underlines, etc, então não se limite a apenas testes com letras.
Buscando nomes de Tabelas
Aqui estamos utilizando o database()
, que serve para utilizarmos como base, o database que está conectado no momento, então altere esse valor caso queira procurar tabelas de outro database.
Buscando nomes de Colunas
Buscando valores de uma Coluna
Sleep
Utilize o sleep
e verifique se ele é processado, ou seja, se apresenta delay na resposta. Caso seja, significa que o alvo está vulnerável a SQL Injection Blind. Obviamente o sleep
não é exclusivo para Blind, porém aqui se torna mais útil, já que no SQL Blind não tem um retorno tão rico de informações.
Caso confirme a existência da vulnerabilidade, podemos fazer queries para validar a existência de dados.
Bypass em Espaços
Quando o alvo estiver barrando espaços, utilize /**/
ou %20
no lugar do espaço, exemplo:
Também podemos usar uma tabulação (HT
ou \t
) para fazer bypass em espaço.
DICA: Para queries simples como admin'or'1'='1
, não precisa de colocar espaços
Bypass em Where
O valor de <table>
abaixo deve ser sempre o mesmo, pois estamos fazendo um join
com a mesma tabela e jogando a condição em seguida, substituindo assim a utilização do where
Bypass em Vírgulas
Caso o WAF não permita que digite vírgula(s), utilize o seguinte padrão:
Bypass em information_schema
Bypass com Encode
Injection em Comentários
Em casos raros na vida real (porém prováveis em CTF), nossos parâmetros (GET ou POST) podem ficar dentros comentários de SQL (/* <param> */
). É possível realizar um bypass utilizando o !
, deixando o código final no seguinte formato:
Comandos Úteis de MySQL
As vezes os comandos abaixo podem não retornar nada ou retornar erro caso esteja utilizando um union
, então se possível deixe os comandos abaixo como um subselect, exemplo: <query_vuln> union all select null, null,(<query_abaixo>) from <table>
Retornando o nome de todos os databases
Retornando o nome de todas as tabelas, separadas por vírgula
Retornando o nome de todas as colunas de uma determinada tabela, separadas por vírgula
Retornando os valores de uma determinada coluna
Lê o conteúdo de determinado arquivo.
OBS.: Caso não consiga utilizar o comando acima, execute o comando SHOW VARIABLES LIKE "secure_file_priv"
para verificar se o módulo de segurança está habilitado.
Outra maneira de lermos arquivo, é utilizando o seguinte comando:
Caso não tenha êxito no comando, acesse o mysql com o seguinte comando: mysql -u <user> -p --enable-local-infile -h <host>
Executa um comando no shell e salva em um arquivo
OBS.: Se nenhum dos dois comando acima funcionar, pode usar o UDF (User Defined Function)
Grava um Shell PHP no diretório do apache.
OBS.: Quando for usar o INTO OUTFILE
, utilize sempre o /
para indicar o caminho absoluto do arquivo que irá salvar, mesmo que o alvo seja um Windows. O mesmo vale para load_file.
Lista os usuários do banco e se tem permissão de escrita (Y).
OBS.: O 0x3a
serve somente para colocar um : (dois pontos) entre o nome do usuário e a permissão que está atribuída.
Também podemos automatizar a permissão deescrita utilizando o Metasploit, porém é preciso ter as credenciais de acesso.
Também podemos descobrir se determinados arquivos existem no servidor.
Conecta no banco e executa uma query, sem ficar no modo interativo.
ATENÇÃO: Atente-se ao p
antes da senha, não coloque espaço entre eles.
Criando um novo usuário no MySql (esteja conectado no MySQL antes):
Fazendo Dump e Restore
GBK
GBK é um conjunto de caracteres chineses simplificados, que podem ser utilizados como aspas simples em um injection, caso o driver do banco de dados do alvo não "fale" o mesmo tipo de caracteres (CHARSET).
Usando a string \xBF'
(que pode ser codificada em URL como %bf%27
), é possível obter um escape.
NOTA: Essa descoberta foi feita em 2006, então vai ser muito raro encontrar esse tipo de situações, porém pode ser útil em CTF's.
Sites
Last updated