Métodos de Escalação de Privilégio no Linux — TryHackMe

Rodrigo Peixoto Santos
19 min readMar 4, 2023

--

Imagem gerada pela IA @Midjourney

Introdução

A pós-exploração é um estágio crucial no processo de um pentest. Nela, o objetivo é obter persistência no sistema alvo e extrair informações para a execução de ações adicionais.

É nesse contexto que surge uma tarefa fundamental: a escalação de privilégios, que consiste em utilizar as mais diversas técnicas de subversão do sistema, seus comandos e serviços, assim como exploits fabricados para obter mais permissões do que possuía inicialmente dentro do alvo.

Essa tarefa é absolutamente necessária durante um pentest, porque demonstra a possível falta de controles no alvo e evidencia que, em caso de uma invasão, seria possível a execução de ações perigosas, com permissões privilegiadas.

Durante este relatório, escrito como parte do Bootcamp de Segurança Ofensiva da Pacific Sec, realizamos as tarefas da sala “Linux PrivEsc” na plataforma TryHackMe. O objetivo desses desafios é permitir a compreensão das técnicas de elevação de privilégios no sistema Linux, visando a obtenção do maior acesso possível.

Link da sala: https://tryhackme.com/room/linuxprivesc

Alvo: Linux PrivEsc — TryHackMe

Utilizamos, para realização da atividade, uma máquina virtual com o Kali Linux configurado e conectado à rede do TryHackMe via OpenVPN.

Ao abrir a sala, vemos que ela possui 21 tarefas, cada uma focada em um tipo de técnica para elevação de privilégios no Linux. Porém, antes de começar a realizar as tarefas, é preciso acessar a máquina virtual.

I — Deploy the Vulnerable Debian VM

A primeira tarefa consiste em estabelecer a conexão com a VM vulnerável aos ataques de escalação de privilégios. Isso pode ser feito através da conexão SSH, conforme demonstrado no comando abaixo.

A princípio, é exibida mensagem de erro, pois a sala exige o uso dos parâmetros -oHostKeyAlgorithms=+ssh-rsa, já que a conexão via OpenSSH não usa o algoritmo RSA, de criptografia, por padrão.

Feito o ajuste, a conexão é estabelecida e é possível obter a flag do primeiro desafio, que pergunta o resultado do comando id.

Uma vez obtido o id e validado o acesso, podemos prosseguir com as demais tarefas da sala.

II — Service Exploits

Todos os sistemas possuem serviços rodando em si, para as mais diversas funções. No entanto, pode ser um problema quando as permissões desses serviços estão mal definidas. No caso desta tarefa, há um usuário root na máquina, porém ele não possui nenhuma senha, permitindo o uso do serviço MySQL para exploração, com base nas suas UDFs (User Defined Functions), que são funções que podem ser carregadas pelo MySQL e executadas como se fossem nativas.

Para iniciar a exploração, nos dirigimos até a pasta do MySQL UDF, com o comando cd.

Feito isso, podemos executar os comandos abaixo para compilar o código do exploit usado para a exploração.

Uma vez executados os comandos, iniciamos o MySQL como root. Como o usuário não possui senha definida, recebemos acesso ao serviço normalmente, porém com permissões de root.

A partir deste ponto, executamos uma série de comandos, que criam a função “do_system” usando o exploit compilado anteriormente.

Após os comandos anteriores podemos, por fim, usar um select para executar a função que irá copiar o conteúdo do /bin/bash para o /tmp/rootbash, além de dar permissão SUID para o arquivo.

Após sair da shell com o comando exit, rodamos o arquivo criado (rootbash) para poder obter o acesso de admin. A ação é feita com o comando /tmp/rootbash -p.

Uma vez com o acesso de adm, excluímos o arquivo com o comando rm, conforme orientação da sala, visto que será criado um novo arquivo posteriormente.

III — Weak File Permissions — Readable /etc/shadow

Um dos arquivos mais importantes no Linux é o arquivo shadow (/etc/shadow), que armazena os hashes das senhas dos usuários do sistema. Esse arquivo, em teoria, deve ser acessível somente pelo root porém, em alguns casos, não há medidas de segurança o suficiente e esse arquivo é legível.

Para testar essa possibilidade, executamos o comando ls -l /etc/shadow e vemos que, de fato, há a permissão de leitura (r). Sendo assim, executamos o cat /etc/shadow, para verificar qual é o conteúdo do arquivo.

Como pode ser visto, o hash da senha do usuário root está exposto. Nota-se que é um hash no formato sha512crypt, pelo seu formato iniciado com $6$. Para dar continuidade à tentativa de acesso, armazenamos o hash da senha do usuário no arquivo hash.txt.

Feito isso, podemos utilizar o John The Ripper para descobrir qual é a senha, com base na famosa wordlist rockyou.txt. Após algum tempo, é exibida a senha de root, que é “password123”.

Com isso, basta usar o comando su root e inserir a senha correta para obter o acesso de administrador no sistema alvo.

IV — Weak File Permissions — Writable /etc/shadow

Nesta tarefa, verificamos novamente as permissões do arquivo /etc/shadow, com uso do comando ls -l. Percebe-se que o arquivo está com permissões indevidas e que é possível escrever nele.

Sabendo disso, criamos um hash de uma senha qualquer, para realização do teste. Nesse caso, um hash no formato SHA-512 para a senha pacific.

Com o editor vim, abrimos o arquivo shadow e substituímos o hash da senha do usuário root para o hash que foi gerado pelo comando mkpasswd anteriormente. Feito isso, basta sair do arquivo salvando-o com :wq.

Com isso, basta logar como root usando a senha pacific. Já que o hash de root corresponde a pacific, o acesso é obtido como root.

V — Weak File Permissions — Writable /etc/passwd

Outro arquivo que pode conter os hashes das senhas é o /etc/passwd. Geralmente, o arquivo é legível por todos, mas só é permitida a escrita pelo usuário root. No entanto, checando as permissões, percebemos que é possível modificá-lo e fazer alterações mesmo sem privilégios.

Cientes disso, podemos gerar um hash da senha pacific e inseri-lo diretamente no arquivo, conforme feito anteriormente no arquivo shadow.

Uma vez editado e salvo o arquivo, pode-se fazer o acesso com o su root e utilizando a senha escolhida (pacific), para a qual foi criado o hash,

Com isso, pode-se também concluir o desafio que pede o resultado do comando id que, quando executado pelo usuário root, exibe o seguinte.

VI — Sudo — Shell Escape Sequences

O comando sudo -l pode ser utilizado para verificar quais comandos o usuário atual pode executar como root. Para início na tarefa, verificamos quais são os executáveis para o user. Dentre os possíveis binários, que podem ser executados sem a necessidade de senha, chama a atenção o do editor de textos nano.

Na página do GTFOBins, verificamos que é possível usar uma sequência de comandos para quebra do shell do Nano e execução de outros comandos.

Dentro do editor, digitamos CTRL+R, seguido de CTRL+X, o que nos permitem a execução de comandos. Utilizamos a sequência reset; sh 1>&0 2:&0, que nos permite sair da simples execução do Nano para uma verdadeira emulação de uma shell privilegiada.

Nesse ponto, apesar de não serem mostrados visualmente, os comandos já são executados.

Acima, os comandos não são mostrados, mas são usados whoami (com resultado root) e id, com o resultado que consta na segunda linha. Podem, então, ser executados quaisquer comandos como root.

Dentre os programas que foram mostrados pelo sudo -l, apenas o apache2 não consta na lista do GTFOBins.

VII — Sudo — Environment Variables

Pesquisando a respeito, podemos obter a informação de que as variáveis de ambiente são nada mais do que valores armazenados pelo Linux, que fornecem informações para os programas em execução, como caminhos dos binários, configurações e outras informações.

Ainda com o comando sudo -l, podemos verificar quais são as variáveis disponíveis para o usuário user.

Vemos que existem as variáveis LD_PRELOAD e LD_LIBRARY_PATH. Enquanto a primeira variável carrega um objeto compartilhado, a segunda contém os diretórios onde são feitas as “varreduras” do SO em busca dos binários.

Criamos, no diretório solicitado, um objeto com nome de preload.so, com base no código que consta na pasta /sudo/preload.c.

Rodamos um dos programas que temos permissão de execução como root, porém com o caminho do LD_PRELOAD definido como o do objeto criado. Assim, quando executado o programa, obtemos uma shell com permissões de root.

Para continuidade da tarefa, saímos da shell privilegiada e executamos o comando ldd /usr/sbin/apache2, que irá listar todas as bibliotecas compartilhadas que o apache2 precisa para sua execução.

Criamos um objeto com o mesmo nome da biblioteca libcrypt.so.1.

Feito isso, pode-se executar o apache2 como SUDO, definido o LD_LIBRARY_PATH como /tmp, a fim de que seja carregado o objeto criado. Uma vez executado o comando, obtemos a shell com permissão de root.

VIII — Cron Jobs — File Permissions

Os Cron Jobs, em resumo, são programas ou scripts que são executados em um tempo pré-definido. Para que funcionem, as informações dos Cron Jobs devem estar armazenadas nas Cron Tabs, sendo a principal a que está em /etc/crontab. Fazemos uma consulta com cat /etc/crontab.

Chamam a atenção dois cronjobs (overwrite.sh e compress.sh), porém não é especificado o caminho do overwrite.sh. Pode ser usado o comando locate overwrite para localizar o arquivo no sistema.

Além disso, podemos verificar que o arquivo está mal configurado e permite que todos modifiquem seu conteúdo. Com o vim, inserimos um script que irá abrir uma conexão com nossa máquina Kali na porta 4444. Feitas as alterações, salvamos o arquivo.

Uma vez salvo o arquivo, iniciamos um listener na máquina Kali com o NetCat. Basta aguardar um tempo para que seja gerada a shell privilegiada, como desejado.

IX — Cron Jobs — PATH Environment Variable

Novamente, verificamos o conteúdo do /etc/crontab. Nota-se que a variável PATH inicia com o caminho /home/user, que é o diretório de nosso usuário.

Criamos, então, um arquivo chamado overwrite.sh que, por sua vez, terá a função de copiar o bin/bash para /tmp/rootbash e dar permissões a ele.

Salvo o arquivo, damos permissões para sua abertura e aguardamos um tempo, para que sejam executadas as tarefas do Cron Job.

Executamos o rootbash criado com /tmp/rootbash -p e obtemos, por fim, o acesso de root na máquina.

X — Cron Jobs — Wildcards

Como visto anteriormente, existem dois cronjobs no arquivo /etc/crontab, sendo um deles o compress.sh. Com o cat, verificamos o seu conteúdo. A parte interessante é que o script está sendo executado com um curinga (*).

Na página do arquivo tar no GTFOBins, podemos verificar que é possível executar comandos, graças à função de checkpoint.

Para a exploração, usamos o msfvenom para gerar um arquivo shell.elf, que fornecerá a shell reversa. O parâmetro LHOST é definido como o IP da máquina Kali na rede do TryHackMe.

Para transferência do arquivo para o alvo, criamos um servidor HTTP.

Em seguida, pode-se usar o comando wget para obtenção do arquivo no alvo. A cópia é realizada com sucesso e podem ser atribuídas as permissões do arquivo com o chmod.

Feito isso, criamos os arquivos que usam o parâmetro checkpoint, para que sejam executados junto ao cronjob.

Ativamos um listener na máquina Kali e, apesar de não exibir exatamente o shell, é possível executar comandos normalmente. A saída é exibida logo abaixo do comando digitado.

XI — SUID / SGID Executables — Known Exploits

Uma das formas mais inteligentes de explorar um alvo é através de exploits conhecidos e vulnerabilidades específicas de algum serviço. Primeiramente, executamos o comando find, com alguns parâmetros para que exiba apenas os programas que têm permissão de SUID.

Nota-se a existência do exim-4.84–3 e pode-se buscar por exploits voltados a ele. Para isso, visitamos o famoso ExploitDB, banco que contém centenas de exploits dos mais diversos temas. Pesquisando por “exim”, localizamos um exploit de 2016 que permite a escalação de privilégios baseado nessa versão do exim.

O Exploit é baseado no CVE 2016–1531, de 2016 e é usado no Linux.

Executamos um script que contém uma cópia do exploit, script já existente no alvo. Uma vez executado, obtemos uma shell privilegiada.

XII — SUID / SGID Executables — Shared Object Injection

Dentro das explorações aos executáveis SUID, existe a de injeção de objeto compartilhado (shared object injection). O arquivo suid-so está vulnerável a essa injeção. Executamos o arquivo e verificamos que ele apenas mostra uma barra de progresso e finaliza.

Com o comando strace, buscamos na saída do arquivo por erros do tipo “no such file”. O executável tenta carregar o libcalc.so no diretório home, mas ele não pode ser localizado.

Criamos, então, o diretório .config para armazenar o arquivo libcalc.co.

Feito isso, compilamos o código libcalc.c, que contém um código de objeto compartilhado. A ideia desse código é simplesmente gerar uma shell.

Executamos o arquivo suid-so e podemos obter o acesso de root, ao invés de apenas uma barra de progresso.

XIII — SUID / SGID Executables — Environment Variables

O arquivo suid-env pode ser explorado por vulnerabilidade nas variáveis de ambiente que utiliza.

Com o comando strings, verificamos quais são as strings legíveis do arquivo.

Dentre elas, vemos a string que inicia o serviço do apache2. Porém, o caminho do comando service não está sendo mostrado. Sabendo disso, compilamos o código service.c em um executável chamado service.

Assim, configuramos a variável PATH adicionando o caminho atual, onde foi gerado o executável service e executamos o suid-env ao mesmo tempo, o que resulta em uma shell com permissões de administrador.

XIV — SUID / SGID Executables — Abusing Shell Features (#1)

O executável suid-env2 é idêntico ao suid-env, exceto pelo fato de que o primeiro mostra o caminho completo do service, para execução do apache2. Isso pode ser visto, novamente, com o comando strings.

Em versões do bash anteriores a 4.2–048, é possível criar funções com nomes similares ao do caminho dos arquivos e depois exportá-las, para que sejam usadas no lugar do caminho verdadeiro. Para checar se isso é possível e qual é a versão do bash, usamos o comando /bin/bash –version.

Sabendo que a versão está dentro dos parâmetros desejados, criamos a seguinte função — de nome “/usr/sbin/service”- e a exportamos.

Com isso, quando o arquivo suid-env2 é executado, recebemos o acesso root no sistema.

XV — SUID / SGID Executables — Abusing Shell Features (#2)

O bash suporta, de acordo com as informações da sala, a existência de um prompt extra para debugging, graças à variável de ambiente PS4. Podemos executar o suid-env2 no modo de debug. Neste caso, a variável PS4 é definida como um comando que será executado no alvo, criando uma versão SUID do /bin/bash.

Uma vez executado o comando, podemos usar o /tmp/rootbash -p para obter acesso a um shell privilegiado.

XVI — Password& Keys — History Files

Caso algum usuário tenha inserido a senha, por acidente, em linha de comando, é possível que ela tenha ficado salva no histórico. Usamos o comando cat ~/.*history | less para exibir as informações.

De fato, vemos no histórico que foi executado um comando mysql, porém tanto usuário (root), quanto sua senha (password123) ficaram expostos no histórico e podem ser usadas.

O comando MySQL usado é mysql -h somehost.local -uroot -ppassword123. Usando o su root e entrando com a senha password123, é possível obter acesso à shell privilegiada.

XVII — Passwords & Keys — Config Files

Os arquivos de configuração podem conter, em alguns casos, credenciais salvas, seja em texto plano ou em outros formatos que, com uso de algumas ferramentas, tornam-se legíveis.

Iniciamos a tarefa visualizando o conteúdo da pasta /home/user e percebemos a existência do arquivo myvpn.ovpn.

Se utilizado o comando cat, é possível perceber que esse arquivo faz referência a um outro arquivo chamado de /etc/openvpn/auth.txt.

Caso feita a leitura, obtemos o login e senha do usuário root e essas credenciais podem ser usadas para acesso ao sistema.

Assim, é realizado acesso como root normalmente, pela sua senha.

XVIII — Passwords & Keys — SSH Keys

Por vezes, são deixados arquivos importantes na máquina, mas nem sempre eles estão com as permissões adequadas. Pesquisamos por arquivos ocultos na pasta raiz (/) com o ls -la. Obtemos diversas pastas como retorno, mas uma delas chama a atenção por ser uma pasta oculta, a pasta .ssh.

Podemos conferir o conteúdo dessa pasta com o ls -l /.ssh. Dentro dela, vemos que há o arquivo root_key, cujo nome é autoexplicativo.

Abrimos o arquivo e copiamos seu conteúdo. Em nossa máquina com o Kali, utilizamos o vim para criar um arquivo com mesmo nome e mesmo conteúdo do que está no alvo.

Atribuímos a ele as devidas permissões, com o chmod 600 root_key, para que seja acessível do alvo. Com o arquivo criado, estabelecemos uma nova conexão ssh com o alvo. Essa conexão, conforme pode ser visto abaixo, é aberta com um shell privilegiado.

XIX — NFS

Segundo a tarefa, os arquivos criados via NFS herdam o ID do usuário remoto. Se o usuário for root e o “root squashing” estiver habilitado, o ID será definido para o usuário “nobody”, não permitindo que o root tenha as permissões de root.

Para começar a exploração, lemos o arquivo /etc/exports.

Notamos que o diretório /tmp está com o root squashing desabilitado, vide a existência do parâmetro no_root_squash. Em nossa máquina Kali, fazemos o acesso como root e damos sequência.

Criamos o diretório /nfs, dentro de /tmp e, logo em seguida, fazemos o compartilhamento dele usando o comando mount.

Ainda no Kali, usamos o msfvenom para criar um payload, com um shell que será salvo no diretório /tmp/nfs.

Salvo o arquivo, garantimos suas permissões para acesso.

Uma vez dadas as permissões, usamos a máquina alvo para se comunicar com o shell no diretório /tmp/ e obtemos, com isso, o acesso root.

XX — Kernel Exploits

Os exploits de Kernel são muito poderosos e, conforme orientação do criador da sala, devem ser usados apenas em último caso. Para começar a exploração, rodamos o Linux Exploit Suggester 2, para identificar possíveis falhas no Kernel do alvo.

Vemos que, além de mostrar os possíveis exploits, a ferramenta dá a referência do CVE, para melhor entendimento.

O famoso exploit Dirty Cow é listado e pode ser usado, conforme abaixo, para substituir o arquivo passwd e gerar uma shell. Compilamos o código no diretório /kernel-exploits/dirtycow e rodamos ele.

Assim que o exploit é concluído, podemos rodar o /usr/bin/passwd para ganhar o acesso à shell privilegiada.

Após o acesso validado como root, restauramos o arquivo original e saímos da shell.

XXI — Privilege Escalation Scripts

Por fim, a última tarefa da sala mostra alguns dos outros scripts possíveis para escalação de privilégios, que buscam por vulnerabilidades automaticamente.

Dentre eles, nos chama a atenção o lse.sh, script que faz uma varredura por diversas vulnerabilidades na máquina e informa se a máquina está vulnerável de alguma forma.

Após a execução do script, podemos verificar algo que foi testado anteriormente: o MySQL pode ser usado sem a necessidade de usar a senha do usuário root. Além disso, são mostradas muitas vulnerabilidades e possíveis pontos de partida para explorações.

Terminam-se assim, as ações no alvo e conclui-se a sala com sucesso.

Mitigação

A escalação de privilégios é uma questão seríssima e seus impactos são tão grandes quanto a dimensão do sistema alvo. O Linux, por ser tão versátil como é, carrega consigo várias vulnerabilidades que podem ser exploradas para a escalar privilégios, incluindo processos em execução, configurações inadequadas, falhas na versão do kernel e problemas de permissão de arquivos e pastas.

Além disso, as próprias ferramentas padrão do sistema podem ser usadas contra ele, como o sudo, que permite que usuários comuns obtenham privilégios de root. O nível de complexidade e os diversos caminhos que podem ser usados para exploração tornam a superfície de ataque enorme.

Recomendamos, para mitigação, a implementação de princípios de privilégio mínimo e restrições máximas de acesso aos recursos do sistema, especialmente arquivos cruciais como /etc/passwd e /etc/shadow. Da mesma forma, é prudente reduzir o número de programas que podem ser executados como sudo (SUID) por um usuário comum, justamente para evitar quebra de shell, como visto neste relatório.

Conclusão

A sala de escalação de privilégio no Linux apresenta grandes desafios, fora do convencional, pois exigem pesquisa e maior entendimento das funções inerentes ao sistema operacional em questão e, além disso, requerem lógica para busca por vulnerabilidades e possíveis exploits.

Como estamos tratando, além de invasões, do entendimento de como funciona o sistema operacional, obtém-se maior aproveitamento. Concluímos, então, que a sala oferece uma oportunidade ímpar para aprendizado e ajuda a entender — com maior profundidade e não se limitando aos scripts prontos — como funcionam os ataques a esse sistema e as possibilidades de exploração dos serviços dele.

Mais uma vez, agradeço por sua presença até aqui, querido(a) leitor(a).

Até a próxima!

--

--

Rodrigo Peixoto Santos

Apenas um apaixonado por CyberSecurity e, no geral, pelo saber.