ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AdFind实战:轻量级LDAP查询工具驱动AD域高效信息收集

AdFind实战:轻量级LDAP查询工具驱动AD域高效信息收集 1. 初识AdFindAD信息收集里的单兵利器AD信息收集听上去是个挺大的词但只要你在企业里管过Windows域环境就知道它落到日常工作里是什么样子财务部说要提供一份“离职超过一年但账号还活着”的清单安全合规要一份“Domain Admins组里到底有谁”的名单新接手的人问“咱这个域的OU结构是什么样的”。早几年我会打开AD用户和计算机一个个点遇到几百上千个对象时手能点酸。后来学会用AdFind一条命令把整份清单拖出来再丢到Excel里做透视效率上完全是两个时代的东西。AdFind是活动目录LDAP查询工具作者Joe Richards整个程序就是一个单文件命令行程序。它不需要安装不需要在域控上装任何客户端组件也不依赖PowerShell的AD模块。它能做什么一句话能说清凡是AD目录里允许通过LDAP查询到的对象信息它都能按你给的筛选条件拉出来。用户、组、计算机、OU、联系人、信任关系这些全在它的能力范围内。对于运维而言它就相当于一个活动目录查询终端和你在数据库里执行SELECT语句是一个思路只不过它查询的后端是AD的目录树语法是LDAP过滤规则。谁适合用它至少三类人。一是AD基础架构运维排查账号状态、清理存量数据、域控迁移前盘点都需要快速批量查对象二是IT审计岗位每个季度出账号和权限归属报表AdFind的纯文本输出很好落到审计记录里三是Helpdesk用户说登录不了你需要快速看账户是否禁用、上次登录时间是什么时候AdFind比远程到DC点鼠标快得多。1.1 它和PowerShell、dsquery的定位差异我绝不是说PowerShell不能干这件事。PowerShell配合ActiveDirectory模块功能很强语法相对友好适合在一次性任务里顺带做复杂计算。但现实情况是你的办公电脑不一定装了RSAT批处理脚本要跨机器跑某些服务器上还未必有这些模块。AdFind的优势是极轻、极稳单文件拷贝即用没有前置依赖输出是标准文本可以直接重定向到txt或CSV脚本友好。dsquery虽然系统自带但它能表达的条件有限遇到userAccountControl这种按位掩码判断的场景就绕不过去。AdFind直接透传LDAP过滤语法能组合的维度丰富得多。我自己的使用习惯是临时查一两个对象用图形界面或dsquery凡是批量信息收集、定时导出、脚本二次处理一律AdFind。工具前置依赖脚本友好度LDAP过滤能力适合场景PowerShell Get-ADUserRSAT/AD模块中需要包一层脚本中高参数封装后略绕一次任务里要顺带做复杂计算dsquery无低低临时单条件查询AdFind无高高批量信息收集、导出、排错这个表基本是我长期使用下来的选择依据你可以先照着这个判断再根据实际环境微调。1.2 这类工具在信息收集里的边界需要先说明一点AdFind只负责“查”不负责“改”。创建、修改、删除这类写操作不是它的本职它也不会绕开AD的权限控制。你拿到的查询结果上限取决于当前账号在域内实际可读的范围。使用最小权限账号跑AdFind能看到的对象就是有限的这是AD权限模型在起作用。日常运维和审计恰好需要这个特性——信息收集的意义是让管理员知道目录里实际有什么而不是猜测应该有什么。2. 上手前的准备跑通第一次查询2.1 工具获取与运行条件AdFind可以从工具作者的原站下载下载后建议解压到一个纯英文目录比如C:\tools\AdFind。整个工具只需要adfind.exe这一个文件。运行条件只有一条能和目标域控连通并且域控的389端口标准LDAP口对当前机器开放。如果你这台电脑已经加域直接在命令行里执行即可工具会自动使用你当前的登录身份去绑定域控如果没加域就需要显式指定账号和密码。开始之前先确认连通性Test-NetConnection dc01.corp.local -Port 389看到TcpTestSucceeded一行为True再继续不然后面报错会干扰判断。2.2 五个核心参数读懂了命令就懂了一半每一条AdFind命令拆开看都是在回答几个问题去哪台服务器查-h、用谁的身份查-u和-p、从哪个位置开始查-b、查什么对象-f、结果怎么输出-dn、-csv、属性列表。参数作用示例-h指定目标域控主机名或IP-h dc01.corp.local-u绑定目录时使用的域账号-u corp\zhangsan-p对应密码-p 密码-b搜索起点即基础DN-b DCcorp,DClocal-fLDAP过滤器决定查询条件-f (objectClassuser)-u的格式建议用“域名\用户名”比如corp\zhangsan这样工具能明确知道账号所属域。-b是搜索起点DN。DN是AD对象的唯一路径类似文件系统里的全路径。查整域就写根目录DCcorp,DClocal查某个OU就写OU销售部,OU华东,DCcorp,DClocal。这个值不熟的话可以在AD用户和计算机里右键对象打开属性编辑器找到distinguishedName抄下来。-f是过滤器后面跟的内容要用英文双引号包起来原因是过滤器中经常出现圆括号和逻辑符号不加引号容易被命令行解释器拆坏。初学阶段只需要记住整个过滤器本身也是一层层的括号表达式多条件就是括号嵌套。2.3 第一次连通测试不急着搞复杂筛选先跑一个能确认链路已经打通的命令adfind -h dc01.corp.local -b DCcorp,DClocal -f (objectClass*) -dn这个命令很短但它会把根DN下所有对象路径都返回一遍。如果能看到一批形如CNxxx,OUxxx,DCcorp,DClocal的字符串说明连接、身份、基础DN三个环节都通了。反之如果报“拒绝访问”或“认证失败”再回到账号权限检查。提示在你已加域的机器上当前登录账号如果只是普通域用户也足够查询绝大多数AD信息。没必要一上来就把域管理员账号填在命令行里先用最小权限跑通流程才是稳妥做法。3. 四种高频信息收集场景用户、组、计算机、OU3.1 用户信息收集把“域里有多少人”变成一条命令想把AD里所有用户对象列出来标准过滤器是组合两个条件adfind -h dc01 -b DCcorp,DClocal -f ((objectCategoryperson)(objectClassuser)) -dn这里为什么要写两个条件很多人不理解。objectCategoryperson利用的是AD索引查询效率高objectClassuser进一步限定对象类型确实是用户。两者搭配是业内筛选用户对象的通用范式能避免把联系人、组等person类对象混进来。需要导出关键字段时把关心的属性名直接排在命令后面adfind -h dc01 -b DCcorp,DClocal -f ((objectCategoryperson)(objectClassuser)) cn sAMAccountName userPrincipalName mail department lastLogon userAccountControl -csv这条命令输出的每一行开头是属性名冒号后面是值。加上-csv后输出会被整理成适合表格处理的格式再配合重定向就可以直接落盘。只找被禁用的账号就要对userAccountControl做按位判断adfind -h dc01 -b DCcorp,DClocal -f ((objectCategoryperson)(objectClassuser)(userAccountControl:1.2.840.113556.1.4.803:2)) -dn这段带长串OID的过滤器是AD里做按位与的固定写法2代表启停位中的“禁用”标志。账号的userAccountControl属性是一个位集合不是单个状态值所以不能用简单的等号判断这在下文第4章会专门展开。3.2 组信息收集与成员归属列所有组adfind -h dc01 -b DCcorp,DClocal -f objectClassgroup name cn distinguishedName -csv查某个组的直接成员比如Domain Adminsadfind -h dc01 -b DCcorp,DClocal -f ((objectClassgroup)(cnDomain Admins)) member返回的member属性是多值属性每个值都是一串DN。如果你想拿到这些DN对应的用户名需要二次回查。比如结果里出现CN张三,CNUsers,DCcorp,DClocal那就再用这条命令查这个DN的细节adfind -h dc01 -b CN张三,CNUsers,DCcorp,DClocal -f (objectClassuser) cn sAMAccountName再往前走一步组里还可能套着组。AD里memberOf字段只记录直接隶属关系多层嵌套需要靠链匹配规则展开。查询一个组的嵌套成员可以用这个过滤器adfind -h dc01 -b DCcorp,DClocal -f ((objectClassuser)(memberOf:1.2.840.113556.1.4.1941:CNDomain Admins,CNUsers,DCcorp,DClocal)) sAMAccountName我常拿它做“谁能管域”这类合规检查比一层层点开组成员快得多。3.3 计算机信息收集资产情况摸底手头有域内所有计算机的型号和系统版本是做资产盘点的重要基础。一次查询就能搞定adfind -h dc01 -b DCcorp,DClocal -f objectCategorycomputer cn operatingSystem operatingSystemVersion lastLogonTimestamp -csv导出后丢进Excel做数据透视系统版本分布、加入域的机器总数、最近有活动迹象的机器几分钟就出结论。做系统升级之前这个清单直接决定工作量评估比拍脑袋靠谱得多。3.4 OU结构收集摸清目录的骨架OU结构相当于AD里的组织文件夹。很多策略下发是按OU层级来的新同事接手环境时最需要的就是这个结构图adfind -h dc01 -b DCcorp,DClocal -f objectClassorganizationalUnit name distinguishedName输出里的每个OU路径就是策略作用范围的最小单位。需要提醒的是OU和容器是两类对象OU可以挂组策略容器不一定。如果查“container”对象要用-f objectClasscontainer别把两者混在一起归类。4. 把筛选条件写精准LDAP过滤语法和位掩码这两个硬骨头4.1 过滤器基础组合LDAP过滤器本质上是一段括号表达式。单个条件是(属性值)。多条件用逻辑符号组合表示与|表示或!表示非。组合后的表达依然带有外层括号。比如找北京分公司且不是禁用状态的账号adfind -h dc01 -b DCcorp,DClocal -f ((objectCategoryperson)(objectClassuser)(department北京)(!(userAccountControl:1.2.840.113556.1.4.803:2))) cn sAMAccountName department -csv这条命令里外层一对圆括号包住多个子条件说明这些条件要同时满足!作内层取反。属性值里有中文时建议确认当前命令行代码页是UTF-8否则查询条件可能先在本地就出现偏差。4.2 位掩码userAccountControl是位集合不是简单整数userAccountControl是AD里一个32位标志位集合每个二进制位表示一种账户属性。新手经常犯的错是拿它当一个状态码去理解。比如看到512就以为是“启用账号”看到514就以为是“禁用账号”然后开始记数字。其实512代表这一位组合里包含“普通账户”标志515、66048这些也是普通账户只是叠加了其他位。常用位的十进制值如下十进制值含义2账号已禁用512正常账户类型65536密码永不过期8388608密码已过期所以标准组合是简单加法普通启用账户常见512普通禁用账户5145122启用且密码永不过期6604851265536。看到66048不要觉得“这不是512是不是状态变了”它就是512加上了65536这个位。按位查询的固定写法是属性:1.2.840.113556.1.4.803:位值这组OID是AD专门约定的按位与匹配规则。想查既禁用又密码永不过期的账号adfind -h dc01 -b DCcorp,DClocal -f ((objectCategoryperson)(objectClassuser)(userAccountControl:1.2.840.113556.1.4.803:2)(userAccountControl:1.2.840.113556.1.4.803:65536)) -dn不要直接写userAccountControl514去查禁用账号因为用户身上随时可能叠加其他标志位值会变得五花八门。按位匹配才是可靠判断。4.3 时间属性处理AD里lastLogon、lastLogonTimestamp、pwdLastSet这些时间属性底层存的是Windows FILETIME格式是一个从1601年1月1日起按100纳秒间隔累计的整数。你在Excel里看到一串十几位数字不是乱码是未转换的原始值。想查最近90天内有过登录记录的账号先算一个阈值$threshold ([DateTime]::UtcNow - [DateTime]::Parse(1601-01-01)).Ticks - 77760000000000 $threshold第二行输出的整数填到过滤器的比较符后面adfind -h dc01 -b DCcorp,DClocal -f ((objectCategoryperson)(objectClassuser)(lastLogon$threshold)) cn sAMAccountName lastLogon -csv需要区分两个属性lastLogon是各域控各自维护的同一账号在不同域控上值不同lastLogonTimestamp跨域复制值有滞后但全局一致。信息收集时按自己场景选属性想精确就多域控分别查再合并想省事就用Timestamp别混为一谈。4.4 为什么要学这套语法LDAP协议本身只认文本过滤规则AdFind只是把查询请求原样传给目录服务不做解释和翻译。因此你写的过滤器优劣直接决定结果准不准。学会这套语法等于掌握了AD查询的核心方言。后面遇到PowerShell里某个cmdlet参数记不清反而可以用AdFind先确认这条LDAP查询通不通再反推cmdlet写法这招在实际排错时很有用。5. 输出控制与自动化从“能查”到“能持续收集”5.1 只输出DN后续循环的基础批量处理场景里DN就是最干净的“索引”。加参数-dn后AdFind只输出对象路径不附带任何属性行适合直接进循环。在命令行窗口里执行循环示例for /f delims %i in (adfind -h dc01 -b DCcorp,DClocal -f ((objectCategorycomputer)(operatingSystem*Windows Server*)) -dn) do echo %i注意这个写法在cmd窗口运行时用%i在.bat批处理文件里要换成%%i。我见过不少人在批处理里照抄命令行版本结果循环变量直接失效这就是其中之一。5.2 CSV导出与Excel导入导出CSV时习惯上我会加两个参数-csv和-nostats。后者能去掉输出末尾的统计信息文件更整洁。adfind -h dc01 -b DCcorp,DClocal -f ((objectCategoryperson)(objectClassuser)) cn sAMAccountName memberOf -csv -nostats users.csv导出后用记事本直接打开中文可能乱码这时候别急。更好的做法是打开Excel用“数据 → 自文本/CSV导入”选择UTF-8编码和逗号分隔乱码和列错位都能规避。直接在资源管理器双击CSV文件Excel默认会用本地代码页解析遇到中文很容易翻车。5.3 定时任务跑批量导出把AdFind查询原封不动写进计划任务就能形成定期数据快照。这里有一个关键原则AdFind是只读查询不修改AD计划任务执行它不会产生配置风险这一点可以放心。但账号安全要上心不要在共享目录放带明文密码的批处理文件。优先让计划任务以域服务账号身份运行脚本里不要写-p参数让AdFind直接使用会话身份完成查询。导出的CSV放到权限受限的共享目录所有人可见的共享盘不适合放账号清单。这样跑出来的历史数据能形成对照比如“上个月还有权限的账号这个月已经没了”这个变化量本身就是审计价值。5.4 结果当存量快照看待信息收集最有意义的用法不是单次查询而是持续留档。我习惯每个月1号跑一次用户、组、计算机三个清单文件按日期命名归档。版本化数据放在那里除了满足合规检查还能做趋势分析账号数量是否异常增长、域内计算机规模是否被没注意到的项目撑大、组内成员变动是否符合团队调整节奏。这些判断全部建立在“先有定期快照”这个前提上。6. 常见问题与排查技巧实录6.1 最常见的报错连不上服务器症状是执行后提示无法连接或找不到服务器。先别急着换脚本按这个顺序查排查项命令说明DNS解析Resolve-DnsName dc01.corp.local确认主机名正确解析端口连通Test-NetConnection dc01.corp.local -Port 389防火墙或域控异常会导致不通服务状态域控上查NTDS服务域控本身是否在正常对外服务经常遇到的是忘了写-h或者-h后面填了一个普通服务器而不是域控。AdFind默认需要域控来响应LDAP查询普通成员服务器不承担目录查询角色指向它自然无结果。6.2 认证失败与权限不足报错集中在“认证失败”“拒绝访问”“无法绑定目录”。原因常见几种密码过期、账号被禁用、账号被锁、密码输入时带了不可见字符。另外即使你的账号是本地管理员也不代表有完整域查询权限这俩是两套体系。这里要单独强调日常脚本里不要长期使用高权限域管理员账号。我见过直接把Administrator密码写在bat文件里的这是双重风险一是脚本文件泄露二是账户行为无法审计。建议单独建一个只读查询账号仅授予需要的读权限把它限定在信息收集这个动作上。6.3 过滤器没结果查出来的结果为空大多数情况不是环境问题是查询条件拼错了。按这个顺序自查-b的基础DN是否写对OU的path层级是否完整。过滤器括号是否成对和|是否放在了外层括号内。属性名是否有拼写错误。AD属性名很多是驼峰比如sAMAccountName、userPrincipalName少一个字母就查不到。值是否匹配实际数据。LDAP对绝大多数属性不强制区分大小写但通配符和特殊字符位置会影响结果。确认查询对象确实存在。可以先去掉-f条件只按-b拉一遍看看该范围内是否有对象。6.4 中文乱码与命令行编码中文环境的下一个大坑是编码。执行命令前可以在cmd里运行chcp 65001把代码页切到UTF-8能解决大部分中文属性值显示和筛选问题。CSV文件的中文更建议走Excel的导入功能选UTF-8而不是直接用记事本打开另存。另一个更稳的做法是让过滤器避免中文。如果部门名是中文可以约定用部门简码或编码字段作为查询条件这样无论脚本在哪个代码页下执行都不会因为中文编码出错。这事看着小却在批量自动化里最咬人。7. 写在最后几件只有长期跑信息收集才会注意的事工具用久了几个习惯慢慢沉淀下来写在这里供你参考。第一固定存放路径。AdFind只有一个文件但我还是建议把它放在C:\tools\AdFind这样的固定目录。不是因为它必须这么做而是脚本里引用工具路径时不能有空格固定路径能减少一半的引号问题。顺便把输出目录也固定所有快照落盘在同一根目录下后续脚本处理会非常顺。第二把时间阈值做成函数。我在第4章写过PowerShell计算FILETIME阈值实际操作时我会把它直接封装成一个函数调用后返回当前时间和90天前的阈值再组合成AdFind参数。这样每个月跑审计时不需要重新手工算一遍数字更不会出现拿半年前的阈值跑本月查询这种低级错误。第三坚持保存原始输出。不要只在Excel里整理完就删掉原始txt原始输出是你所有结论的唯一依据。将来合规检查需要回溯“某月的查询依据是什么”时原始txt比整理后的表更可信。第四给账号分级。信息收集这个场景只需要一个能查询的只读账号。别图省事把域管理员绑定在导出脚本里更不要把它写到任何共享目录。用最小权限账号跑查询既是安全要求也是给审计保留清晰痕迹。最后分享一件亲历的事我第一次拿AdFind做全量账号清单时意外发现一批多年没登录的系统账号其中一个还挂着较高的权限组。当时没有这个工具我不会想到系统里还蹲着这么老的隐藏对象。AD这套目录复杂就复杂在你不去查它就静悄悄躺在那里。定期用AdFind翻一遍把账号、组、计算机的状态摸清楚很多隐患在变成事故之前其实都是有机会看到的。
返回列表