CVE-2020-1301 Windows SMB Authenticated远程代码执行漏洞分析说明
一、漏洞信息
1. 漏洞简述
漏洞名称:Windows SMB Authenticated Remote Code Execution Vulnerability
漏洞编号:CVE-2020-1301
漏洞类型:Integer Overflow
2. 组件概述
Microsoft Windows的所有版本均附带服务器消息块(SMB)协议的实现。 SMB是本机Windows网络框架,支持文件共享,网络打印,远程过程调用和其他功能。在Windows系统上,SMB协议通过附加的安全性,文件和磁盘管理支持扩展了CIFS协议。 通过各种SMB命令和子命令类型提供这些功能。
3. 漏洞利用
该漏洞利用需要攻击者拥有一个经过认证的账户,通过向目标server发送特制的SMBv1消息来触发漏洞。成功利用该漏洞的攻击者可以实现任意代码执行。
4. 漏洞影响版本
• Microsoft Windows 7
• Microsoft Windows 8.1
• Microsoft Windows 10
• Microsoft Windows RT 8.1
• Microsoft Windows Server 2008
• Microsoft Windows Server 2008 R2
• Microsoft Windows Server 2012
• Microsoft Windows Server 2012 (Server Core installation)
• Microsoft Windows Server 2012 R2
• Microsoft Windows Server 2012 R2 (Server Core installation)
• Microsoft Windows Server 2016
• Microsoft Windows Server 2016 (Server Core installation)
• Microsoft Windows Server 2019
• Microsoft Windows Server 2019 (Server Core installation)
• Microsoft Windows Server version 1803 (Server Core Installation)
• Microsoft Windows Server version 1903 (Server Core installation)
• Microsoft Windows Server version 1909 (Server Core installation)
• Microsoft Windows Server version 2004 (Server Core installation)
5. 解决方案
微软官方已针对该漏洞发布了安全更新补丁,补丁地址如下: https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2020-1301
二、漏洞复现
1. 环境搭建
靶机:win7_sp1_x86
攻击机:win10
靶机特定文件开启SMB共享,并创建对应的访问用户,用户权限任意。
2. 复现过程
在攻击机中运行poc:
python2 poc.py -t ip -u name -p passwd靶机蓝屏:
三、漏洞分析
1. 漏洞基本信息
漏洞文件:srv.sys
漏洞函数:SrvSmbNtolctl()
漏洞参数:SMBv1协议FSCTL_SIS_COPYFILE请求中的SourceFileNameLength和DestinationiFileNameLength字段
漏洞对象:一个动态分配的buffer
2. 背景知识
SMB_COM_NT_TRACSACT子命令扩展了SMB_COM_TRANSACTION2命令的文件系统功能访问,允许传输非常大的参数和数据块。SMB_COM_NT_TRANSACT 消息可以超过单个SMB消息的最大大小(由MaxBufferSize会话参数的值确定)。 在这种情况下,client将会使用一个或多个SMB_COM_NT_TRANSACT_SECONDARY消息来传输Data和Parameters相关字节数据。
SMB_COM_NT_TRANSACT命令请求消息与其他两种SMB的transaction请求message存在一定不同。 尽管有几个公共字段,但SMB_COM_NT_TRANSACT消息会重新排列字段以提供更好的字节对齐。 其他transaction类型使用16位大小的字段来提供参数和数据的大小和偏移量, SMB_COM_NT_TRANSACT使用32位大小的字段,主要目的就是为了更大的数据传输。 此外SMB_COM_NT_TRANSACT还包含一个Function字段,其中包含子命令代码。SMB_COM_NT_TRANSACT 结构如下:
// SMB_Parameters节:包含用于管理transaction本身的信息,还包含标志和设置信息,这些标志和设置信息为在服务器端执行操作提供了上下文。SMB_Parameters { UCHAR WordCount;//指定参数块中SMB参数words的总数,该字段值必须大于或等于0x13 Words { UCHAR MaxSetupCount;//client在transaction reply中允许的最大setup字节数 USHORT Reserved1;//2字节的paddling数据,必须设置为0x0000,用于字节对齐 ULONG TotalParameterCount;//请求中传输的transaction parameters的byte数 ULONG TotalDataCount;//请求中传输的transaction data的byte数 ULONG MaxParameterCount;//client在transaction reply中允许的最大parameters字节数 ULONG MaxDataCount;//client在transaction reply中允许的最大data字节数 ULONG ParameterCount;//在当前SMB message中传输的transaction parameter字节数。如果transaction是单个的SMB_COM_NT_TRANSACT请求,该字段的值必须等于TotalParameterCount字段的值。如果该值比TotalParameterCount字段的值小,那么至少要存在一个SMB_COM_NT_TRANSACT_SECONDARY消息。 ULONG ParameterOffset;//transaction parameters的偏移量,从SMB_Header开始计算 ULONG DataCount;//在当前SMB message中传输的transaction data字节数 ULONG DataOffset;//transaction data的偏移量,从SMB_Header开始计算 UCHAR SetupCount;//transaction请求中包含的setup word数 USHORT Function;//transaction中的子命令,指明了server要进行的操作 USHORT Setup[SetupCount];//2字节word的数组,指明了transaction的上下文 } }//SMB_Data部分包含的parameter和data是服务器上transaction操作的输入SMB_Data { USHORT ByteCount;// SMB_Data.Bytes 数组中的byte数 Bytes { UCHAR Pad1[];//填充字节数组 UCHAR NT_Trans_Parameters[ParameterCount];//transaction parameter字节 UCHAR Pad2[];//填充字节数组 UCHAR NT_Trans_Data[DataCount];//transaction data字节 } }3. 详细分析
1. 漏洞触发相关结构
本漏洞的触发主要与Function字段相关,使用的子命令为NT_TRANSACT_IOCTL。该子命令允许将文件系统控制和设备控制功能从客户端透明地传输到服务器,并用于向服务器发送特定于平台或特定于实现的信息,其结构如下:
NT_Trans_Parameters { } NT_Trans_Data { UCHAR Data[TotalDataCount]; }前面SMB_Parameters部分:
字段大小(byte)说明WordCount1UCHAR,值必须为0x17Words46USHORT的一个数组TotalParameterCoun2USHORT,值为0MaxParameterCount2USHORT,值为0ParameterCount2USHORT,值为0SetupCount1UCHAR,值必须为0x04Function2USHORT,值必须为0x0002(NT_TRANSACT_IOCTL)Setup字段的格式如下:
字段大小 (byte)说明FunctionCode4文件系统控件或设备控件(FSCTL / IOCTL)方法的控制代码FID2必须包含从先前成功的SMB打开命令获得的有效FID,提供的FID的类型由IsFsctl指定IsFsctl1如果命令是文件系统控制命令,而FID是文件系统控制设备,则此字段为TRUE。IsFlags1如果设置了位0,则该命令将应用于共享根句柄与本漏洞相关的是FSCTL_SIS_COPYFILE,code为0x90100。该请求消息会请求server使用single instance storage(SIS) fileter来copy文件,该消息包含一个SI_COPYFILE data元素。 如果服务器上安装了SIS fileter,将通过创建SIS link的方式来替代实际复制文件数据的方式,将指定的源文件复制到指定的目标文件。 FSCTL_SIS_COPYFILE请求结构如下:
字段大小(byte)说明SourceFileNameLength432位大小的unsigned integer,指明SouceFileName的大小(包含结尾处的空字符)eDestinationFileNameLength432位大小的unsigned integer,指明DestinationFileName的大小(包含结尾处的空字符)Flags432位大小的unsigned integer,包含0或多个flag值SourceFileNamevariable以空值结尾的Unicode字符串,包含源文件名DestinationFileNamevariable以空值结尾的Unicode字符串,包含目标文件名2. 漏洞产生原因
Windows SMB server的内核驱动在处理NT_TRANSACT_IOCTL子命令中的FSCTL_SIS_COPYFILE命令请求时,由于验证不充分产生了一个整数溢出漏洞。
当server在处理NT_TRANSACT_IOCTL命令请求时,会分配一个内核内存池用作缓冲区,来存储处理文件系统请求时产生的中间数据。其存储方式如下:
[absoluteSourceFileNameLength][absoluteDestinationFileNameLength][Flags][absoluteSourceFileName][absoluteDestinationFileName]absoluteSourceFileName和absoluteDestinationFileName字符串与SMB连接的共享路径(取决于SMB_COM_TREE_CONNECT_ANDX请求中的Path字段)以及FSCTL_SIS_COPYFILE请求中的各自SourceFileName和DestinationFileName字段串联在一起。在复制这些绝对文件名时就会产生漏洞。
为了将文件名创建到前面说到的内核内存池中,首先将共享路径复制到内存池中,然后检查共享文件名是否以'\'结尾。如果是,进一步检查SourceFileName或DestinationFileName的第一个字符是否位'\'或'\0';如果是,就使用memcpy函数从SourceFileName或DestinationFileName的第二个字符开始复制,复制的长度为SourceFileNameLength - 2或DestinationFileNameLength - 2。漏洞触发主要由于没有检查这两个长度是否大于1。如果SourceFileNameLength或者DestinationFileNameLength的值为1,那么就会发生整数溢出,复制长度变为了0xffffffff,从而会溢出前面分配的内存池缓冲区。
3. 静态分析
此处使用的srv.sys软件版本为:6.1.7601.17514。
首先将SI_COPYFILE结构各字段值设置如下:
FieldValueSourceFileNameLength0x0000000aDestinationFileNameLength0x00000001Flags0x00000002SourceFileName000000000000000000DestinationFileName00查看SrvSmbNtIoctl()函数如下:
相关的关键代码在图中已做了注释,容易看出,整数溢出的位置有两处,都可以产生0xffffffff的值。该值随后传入到后续的内存分配代码:
在使用memcpy()进行内存分配时,会尝试将0xffffffff字节从目标文件名(或者源文件名)复制到先前分配的SMB1缓冲区,因此会发生溢出崩溃。
4. 动态分析
栈回溯结果:
栈回溯结果显示关键函数在srv!SrvSmbNtIoctl+0x7a4(),而该位置恰好为memcpy()函数执行完返回的地址:
4. 源码分析
此处没有找到对应版本的源码,使用一个近似版本的源码:
copyFile = (PSI_COPYFILE)transaction->InData; --------- source = copyFile->FileNameBuffer; sourceLength = copyFile->SourceFileNameLength; dest = source + (sourceLength / sizeof(WCHAR)); destLength = copyFile->DestinationFileNameLength; ---- if ( (sourceLength > bufferLength || sourceLength == 0 ) || (destLength > bufferLength || destLength == 0 ) || ((FIELD_OFFSET(SI_COPYFILE,FileNameBuffer) + sourceLength + destLength) > bufferLength) || (*(source + (sourceLength/sizeof(WCHAR)-1)) != 0) || (*(dest + (destLength/sizeof(WCHAR)-1)) != 0) ) { //这里检查这两个字段是否为偶数 SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER ); return SmbTransStatusErrorWithoutData; } ---- addSlashToSource = 0; addSlashToDest = 0; if ( IS_UNICODE_PATH_SEPARATOR(*(prefix + (prefixLength/sizeof(WCHAR)-1))) ) { if ( IS_UNICODE_PATH_SEPARATOR(*source) ) { source++; sourceLength -= sizeof(WCHAR); // sourceLength = 1 - 2 = 0xFFFFFFFF, 发生溢出 } if ( IS_UNICODE_PATH_SEPARATOR(*dest) ) { dest++; destLength -= sizeof(WCHAR); // destLength = 1 – 2 = 0xFFFFFFFF, 发生溢出 } } else { if ( !IS_UNICODE_PATH_SEPARATOR(*source) ) { ---- RtlCopyMemory( p, source, sourceLength ); p += sourceLength; RtlCopyMemory( p, prefix, prefixLength ); p += prefixLength; if ( addSlashToDest != 0 ) { *(PWCHAR)p = UNICODE_DIR_SEPARATOR_CHAR; p += sizeof(WCHAR); } RtlCopyMemory( p, dest, destLength );5. 攻击流量
执行poc,抓取到的流量如下所示:
6. PoC分析
该漏洞的poc代码已在互联网中公开,可自行网上进行搜索。此处给出关键字段的数值构造:
IoctlCode = 0x90100setup = smb.pack('
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
楼主热帖