LDAP学习
RSAT
背景
Remote Server Administration Tools(RSAT)自 Windows 2000 时代起就是 Windows 的一部分。RSAT 允许系统管理员从运行 Windows 10、Windows 8.1、Windows 7 或 Windows Vista 的工作站上,远程管理 Windows Server 角色和功能。RSAT 只能安装在 Windows 的 Professional 或 Enterprise 版本上。在企业环境中,RSAT 可以远程管理 Active Directory、DNS 等服务
工具列表
- SMTP Server Tools
- Hyper-V Management Tools
- Hyper-V Module for Windows PowerShell
- Hyper-V GUI Management Tools
- Windows Server Update Services Tools
- API and PowerShell cmdlets
- User Interface Management Console
- Active Directory Users and Computers Snap-in
- Active Directory Sites and Services Snap-in
- Active Directory Domains and Trusts Snap-in
- Active Directory Administrative Center Snap-in
- ADSI Edit Snap-in
- Active Directory Schema Snap-in (Not Registered)
- Active Directory Command Line Tools
- Active Directory Module for Windows PowerShell
- IIS Management Tools
- IIS Management Console
- IIS Management Compatibility
- Feature Tools
- Remote Desktop Services Tools
- Role Tools
- Update Services Tools
- Group Policy Tools
枚举
如果我们攻陷了一台已加入域的系统(或者客户要求我们从他们的一台工作站执行 AD 评估),就可以利用 RSAT 来枚举 AD
另外,如果一台主机没有加入域,只要它所在的子网可以与域控制器通信,我们也可以通过命令行使用 “runas” 启动任意 RSAT 管理单元来枚举域。这个方法在内部评估中尤其有用:当我们获得了有效的 AD 凭据,并希望从 Windows 虚拟机上执行枚举时,可以这样操作。
我们也可以在未加入域的计算机上使用下面的命令语法打开 MMC Console:1
runas /netonly /user:Domain_Name\Domain_USER mmc
概述
LDAP(Lightweight Directory Access Protocol,轻量级目录访问协议)是 Active Directory 的核心组成部分。最新 LDAP 规范为第 3 版,发布为 RFC 4511。理解 LDAP 在 AD 环境中的工作方式,对攻击者和防守者都非常重要。
LDAP 是开源、跨平台的目录服务访问协议,可用于对 AD 等目录服务进行认证和查询。AD 存储用户账户和安全信息,并让网络中的其他设备共享这些信息。LDAP 就是应用程序与目录服务器通信的“语言”。换句话说,网络系统通过 LDAP 与 AD 交谈。
LDAP 会话首先连接到 LDAP 服务器,也称 Directory System Agent。AD 中的域控制器会监听 LDAP 请求,包括安全认证请求。AD 与 LDAP 的关系可类比为 Apache 与 HTTP:Apache 是使用 HTTP 协议的 Web 服务器,AD 是使用 LDAP 协议的目录服务器。少数环境可能没有 AD 但使用 LDAP,例如 OpenLDAP。
认证
LDAP 通过 BIND 操作对 AD 凭据进行认证,并为 LDAP 会话设置认证状态。LDAP 认证主要有两类:
- 简单认证:包括匿名认证、未认证认证以及用户名/密码认证。用户名和密码会构造 BIND 请求提交给 LDAP 服务器。
- SASL 认证:Simple Authentication and Security Layer 使用 Kerberos 等其他认证服务绑定 LDAP 服务器,再通过该认证服务完成 LDAP 认证。SASL 将认证方法与应用协议分离,能提供更好的安全性。
默认情况下,LDAP 认证消息以明文发送,内部网络中的攻击者可能嗅探 LDAP 消息。因此建议使用 TLS 或类似加密手段保护传输过程。
匿名查询
可以使用 LDAP 查询向目录服务请求信息。
LDAP 查询非常强大,可用于收集大量信息、绘制 AD 环境结构、发现错误配置。后续章节将深入讲解 AD 与 LDAP 搜索过滤器。
Windapsearch
Windapsearch 是一个 Python 脚本,可通过 LDAP 查询执行匿名或认证的 AD 用户、组、计算机枚举。它可替代需要手写复杂 LDAP 查询的 ldapsearch。使用空用户名 -u “” 可确认 LDAP NULL session,并可用 —functionality 查看域功能级别。1
2
3python3 windapsearch.py --dc-ip 10.129.1.207 -u "" --functionality
python3 windapsearch.py --dc-ip 10.129.1.207 -u "" -U
python3 windapsearch.py --dc-ip 10.129.1.207 -u "" -C
凭证化LADP枚举
与 SMB 类似,一旦拥有域凭据,就可以从 LDAP 提取大量信息,包括用户、组、计算机、信任、GPO、域密码策略等。ldapsearch-ad.py 与 windapsearch 都适合做此类枚举。
Windapsearch
1 | windapsearch --dc-ip 10.129.1.207 -u inlanefreight\james.cross --da |
这些命令可枚举 Domain Admins 以及拥有非约束委派的用户。
ldapsearch-ad
1 | ldapsearch-ad -l 10.129.1.207 -d inlanefreight -u james.cross -p Summer2020 -t pass-pols |
这些内置查询能快速拉取密码策略、可能被 Kerberoasting 的用户,以及可被 ASREPRoasting 的用户。
Windows下进行查询
进行渗透测试时,往往需要查看当前域中的用户、组、计算机、OU、GPO、委派、SPN、密码策略等信息。
在 Windows 上做 LDAP 查询主要有两种方式:
在 Windows 上做 LDAP 查询主要有两种方式:
- 有 AD PowerShell 模块:
Get-ADUser / Get-ADGroup / Get-ADComputer / Get-ADObject - 没有 AD PowerShell 模块:
使用.NET DirectorySearcher,也就是[ADSISearcher]
如果目标机器是域内主机,但没有安装 RSAT / ActiveDirectory 模块,[ADSISearcher] 通常更加实用。
查询当前域 Base DN
LDAP 查询首先需要知道当前域的 Base DN。
例如域名是:
1 | inlanefreight.local |
对应的 Base DN 通常是:
1 | DC=inlanefreight,DC=local |
使用 PowerShell 查询 RootDSE
1 | ([ADSI]"LDAP://RootDSE").defaultNamingContext |
示例结果:
1 | DC=inlanefreight,DC=local |
也可以查询更多 RootDSE 信息:
1 | [ADSI]"LDAP://RootDSE" |
常见字段:
1 | defaultNamingContext 当前域 |
如果安装了 AD 模块:1
2Get-ADRootDSE
Get-ADDomain | Select-Object DNSRoot,DistinguishedName
使用 AD PowerShell 模块查询
如果机器上存在 ActiveDirectory 模块,可以直接使用:1
Import-Module ActiveDirectory
查看是否存在模块:1
Get-Module -ListAvailable ActiveDirectory
查询域用户
查询所有用户:
1 | Get-ADUser -Filter * | Select-Object Name,SamAccountName,DistinguishedName |
查询指定用户:
1 | Get-ADUser -Identity james.cross | Select-Object Name,SamAccountName,DistinguishedName |
按 LDAPFilter 查询:
1 | Get-ADUser -LDAPFilter "(sAMAccountName=james.cross)" | Select-Object Name,SamAccountName,DistinguishedName |
查询用户详细属性:
1 | Get-ADUser -Identity james.cross -Properties * | Select-Object Name,SamAccountName,Description,MemberOf,LastLogonDate,PasswordLastSet |
查询域组
查询所有组:
1 | Get-ADGroup -Filter * | Select-Object Name,SamAccountName,DistinguishedName |
查询管理员相关组:
1 | Get-ADGroup -Filter 'Name -like "*admin*"' | Select-Object Name,DistinguishedName |
查询指定组成员:
1 | Get-ADGroupMember "Domain Admins" |
递归查询嵌套组成员:
1 | Get-ADGroupMember "Domain Admins" -Recursive |
查询某个用户属于哪些组:
1 | Get-ADUser james.cross -Properties MemberOf | Select-Object -ExpandProperty MemberOf |
查询域计算机
查询所有计算机:
1 | Get-ADComputer -Filter * | Select-Object Name,DNSHostName,OperatingSystem,DistinguishedName |
查询 Windows Server:
1 | Get-ADComputer -Filter 'OperatingSystem -like "*Server*"' -Properties OperatingSystem | Select-Object Name,DNSHostName,OperatingSystem |
查询域控:
1 | Get-ADDomainController -Filter * | Select-Object HostName,IPv4Address,Site,Domain |
查询 OU
1 | Get-ADOrganizationalUnit -Filter * | Select-Object Name,DistinguishedName |
指定 OU 下查询用户:
1 | Get-ADUser -Filter * ` -SearchBase "OU=Users,DC=inlanefreight,DC=local" | Select-Object Name,SamAccountName |
查询 GPO
1 | Get-GPO -All |
查询 GPO 名称和 GUID:
1 | Get-GPO -All | Select-Object DisplayName,Id,Owner |
如果没有 GroupPolicy 模块,也可以使用 LDAP 查询:
1 | Get-ADObject -LDAPFilter "(objectClass=groupPolicyContainer)" ` -SearchBase "CN=Policies,CN=System,DC=inlanefreight,DC=local" ` -Properties displayName,gPCFileSysPath | Select-Object displayName,gPCFileSysPath,DistinguishedName |
使用 ADSISearcher 查询
如果没有 AD 模块,可以直接使用 PowerShell 内置的 .NET DirectorySearcher。
基础模板:
1 | $Searcher = New-Object DirectoryServices.DirectorySearcher$Searcher.SearchRoot = "LDAP://DC=inlanefreight,DC=local"$Searcher.Filter = "(objectClass=user)"$Searcher.FindAll() |
也可以写成简写形式:
1 | ([ADSISearcher]"(objectClass=user)").FindAll() |
ADSISearcher 查询用户
查询所有用户:
1 | ([ADSISearcher]"(&(objectCategory=person)(objectClass=user))").FindAll() |
只输出用户名:
1 | ([ADSISearcher]"(&(objectCategory=person)(objectClass=user))").FindAll() | ForEach-Object { $_.Properties.samaccountname } |
查询指定用户:
1 | ([ADSISearcher]"(sAMAccountName=james.cross)").FindOne() |
输出指定属性:
1 | ([ADSISearcher]"(sAMAccountName=james.cross)").FindOne().Properties |
ADSISearcher 查询组
查询所有组:
1 | ([ADSISearcher]"(objectClass=group)").FindAll() | ForEach-Object { $_.Properties.cn } |
查询 Domain Admins:
1 | ([ADSISearcher]"(cn=Domain Admins)").FindOne().Properties |
查询组成员:
1 | ([ADSISearcher]"(cn=Domain Admins)").FindOne().Properties.member |
ADSISearcher 查询计算机
1 | ([ADSISearcher]"(objectClass=computer)").FindAll() | ForEach-Object { $_.Properties.dnshostname } |
查询服务器:
1 | ([ADSISearcher]"(&(objectClass=computer)(operatingSystem=*Server*))").FindAll() | ForEach-Object { $_.Properties.dnshostname $_.Properties.operatingsystem } |
常见 LDAP 过滤器
LDAP 查询最重要的是过滤器。
格式大概如下:
1 | (属性=值) |
多个条件组合:
1 | (&(条件1)(条件2)) |
用户查询过滤器
查询所有用户:
1 | (&(objectCategory=person)(objectClass=user)) |
查询指定用户名:
1 | (sAMAccountName=james.cross) |
查询存在邮箱的用户:
1 | (&(objectCategory=person)(objectClass=user)(mail=*)) |
查询描述字段不为空的用户:
1 | (&(objectCategory=person)(objectClass=user)(description=*)) |
查询被禁用用户:
1 | (&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2)) |
查询未禁用用户:
1 | (&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))) |
查询密码永不过期用户:
1 | (&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=65536)) |
查询不需要 Kerberos 预认证的用户,常用于 ASREPRoasting 目标发现:
1 | (&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304)) |
组查询过滤器
查询所有组:
1 | (objectClass=group) |
查询指定组:
1 | (cn=Domain Admins) |
查询管理员相关组:
1 | (cn=*Admin*) |
查询某用户所在组:
1 | (member=CN=James Cross,OU=Users,DC=inlanefreight,DC=local) |
查询某组的嵌套成员:
1 | (member:1.2.840.113556.1.4.1941:=CN=James Cross,OU=Users,DC=inlanefreight,DC=local) |
计算机查询过滤器
查询所有计算机:
1 | (objectClass=computer) |
查询服务器:
1 | (&(objectClass=computer)(operatingSystem=*Server*)) |
查询 Windows 10:
1 | (&(objectClass=computer)(operatingSystem=*Windows 10*)) |
查询域控:
1 | (&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192)) |
SPN 查询过滤器
查询配置了 SPN 的用户,常用于 Kerberoasting 目标发现:
1 | (&(objectCategory=person)(objectClass=user)(servicePrincipalName=*)) |
PowerShell:
1 | Get-ADUser -LDAPFilter "(&(objectCategory=person)(objectClass=user)(servicePrincipalName=*))" ` -Properties servicePrincipalName | Select-Object SamAccountName,ServicePrincipalName |
ADSISearcher:
1 | ([ADSISearcher]"(&(objectCategory=person)(objectClass=user)(servicePrincipalName=*))").FindAll() | ForEach-Object { $_.Properties.samaccountname $_.Properties.serviceprincipalname } |
委派查询过滤器
查询非约束委派用户:
1 | (&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=524288)) |
查询非约束委派计算机:
1 | (&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288)) |
查询约束委派:
1 | (msDS-AllowedToDelegateTo=*) |
查询 RBCD:
1 | (msDS-AllowedToActOnBehalfOfOtherIdentity=*) |
PowerShell:
1 | Get-ADObject -LDAPFilter "(msDS-AllowedToDelegateTo=*)" ` -Properties msDS-AllowedToDelegateTo | Select-Object Name,ObjectClass,msDS-AllowedToDelegateTo |
1 | Get-ADObject -LDAPFilter "(msDS-AllowedToActOnBehalfOfOtherIdentity=*)" ` -Properties msDS-AllowedToActOnBehalfOfOtherIdentity | Select-Object Name,ObjectClass,DistinguishedName |
Linux 下 ldapsearch 查询
Linux 下可以使用原生 ldapsearch。
它比 windapsearch 和 ldapsearch-ad 更底层,需要手动指定:
1 | -H LDAP 服务器 |
基础格式:
1 | ldapsearch -x \ |
查询 Base DN
1 | ldapsearch -x \ |
带凭据:
1 | ldapsearch -x \ |
查询用户
1 | ldapsearch -x \ |
查询指定用户:
1 | ldapsearch -x \ |
查询组
1 | ldapsearch -x \ |
查询 Domain Admins:
1 | ldapsearch -x \ -H ldap://10.129.1.207 \ -D 'inlanefreight\james.cross' \ -W \ -b 'DC=inlanefreight,DC=local' \ '(cn=Domain Admins)' \ cn member distinguishedName |
查询计算机
1 | ldapsearch -x \ -H ldap://10.129.1.207 \ -D 'inlanefreight\james.cross' \ -W \ -b 'DC=inlanefreight,DC=local' \ '(objectClass=computer)' \ cn dNSHostName operatingSystem distinguishedName |
查询 SPN
1 | ldapsearch -x \ |
查询 ASREPRoast 目标
1 | ldapsearch -x \ |
查询密码策略
1 | ldapsearch -x \ |
