CVE-2021-3438:SSPORT.SYS打印机驱动漏洞分析

robots

 

基本情况

2021年2月18日,SentinelLabs向惠普报告了其在打印机驱动程序中发现的严重漏洞,该漏洞影响380多款不同的HP和Samsung打印机,以及十几种Xerox打印机产品。该漏洞编号为CVE-2021-3438,CVSS评分8.8分,由于其存在模块从2005年开始发布,因此影响范围较大。目前该漏洞已完成修复,惠普和Xerox分别发布了针对该漏洞的安全更新信息HPSBPI03724XRX21K

 

漏洞分析

该漏洞出现的模块是SSPORT.SYS,该文件在点击打印机驱动安装程序之后,无论是否完成安装,该文件都会静默安装到C:\Windows\System32\Drivers路径下,且被激活。该文件是一个古老的驱动的驱动文件,文件大小只有十几K,下图可以看出驱动文件包含微软的签名:

SSPORT.SYS签名

下面以HP_Color_Laser_150_Full_Software_and_Drivers_1.14.exe和HP_Color_Laser_150_Full_Software_and_Drivers_1.16.exe安装程序为例,分析该漏洞的基本情况。使用虚拟机快照,分别在windows 10上安装这两个驱动安装程序,安装后从C:\Windows\System32\Drivers路径中获取SSPORT.SYS驱动文件,两个驱动文件的函数基本情况如下:

1.14版本SSPORT.SYS函数情况

1.14版本SSPORT.SYS函数情况

1.16版本SSPORT.SYS函数情况

1.16版本SSPORT.SYS函数情况

1.14版本DriverEntry函数为:

NTSTATUS __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
NTSTATUS result; // eax
int v4; // ebx
PDEVICE_OBJECT DeviceObject; // [rsp+40h] [rbp-38h] BYREF
struct _UNICODE_STRING DestinationString; // [rsp+48h] [rbp-30h] BYREF
struct _UNICODE_STRING SymbolicLinkName; // [rsp+58h] [rbp-20h] BYREF

DeviceObject = 0i64;
RtlInitUnicodeString(&DestinationString, L"\\Device\\SSPORT");
result = IoCreateDevice(DriverObject, 0, &DestinationString, 0x22u, 0x100u, 0, &DeviceObject);
if ( result >= 0 )
{
    DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)&sub_15000;
    DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)&sub_15000;
    DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)sub_15070;
    DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_15030;
    RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\ssportc");
    v4 = IoCreateSymbolicLink(&SymbolicLinkName, &DestinationString);
    if ( v4 < 0 )
    IoDeleteDevice(DeviceObject);
    result = v4;
}
return result;
}

1.16版本DriverEntry函数为:

NTSTATUS __stdcall DriverEntry(_DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath)
{
NTSTATUS result; // eax
int v4; // ebx
struct _UNICODE_STRING DeviceName; // [rsp+40h] [rbp-28h] BYREF
struct _UNICODE_STRING DestinationString; // [rsp+50h] [rbp-18h] BYREF
PDEVICE_OBJECT DeviceObject; // [rsp+80h] [rbp+18h] BYREF

DeviceObject = 0i64;
RtlInitUnicodeString(&DeviceName, aDeviceSsport);
result = IoCreateDevice(DriverObject, 0, &DeviceName, 0x22u, 0x100u, 0, &DeviceObject);
if ( result >= 0 )
{
    DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)sub_15008;
    DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)sub_15008;
    DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)sub_15074;
    DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_15030;
    RtlInitUnicodeString(&DestinationString, aDosdevicesSspo);
    v4 = IoCreateSymbolicLink(&DestinationString, &DeviceName);
    if ( v4 < 0 )
    IoDeleteDevice(DeviceObject);
    result = v4;
}
return result;
}

简单分析可以发现,1.14和1.16的核心处理函数分别为sub_15070和sub_15074,这两个函数的关键处理代码对比如下:

sub_15070函数:

__int64 __fastcall sub_15070(__int64 a1, __int64 a2)
{
    ------//省略部分代码
    v10 = *(char **)(a2 + 24);
    v11 = v10;
    v12 = (char *)((char *)qword_11030 - v10);
    while ( 1 )
    {
      v13 = *v11;
      if ( *v11 != v12[(_QWORD)v11] )
        break;
      ++v11;
      if ( !v13 )
      {
        v14 = 0;
        goto LABEL_13;
      }
    }
    v14 = -((unsigned __int8)*v11 < (unsigned int)v12[(_QWORD)v11])
        - (((unsigned __int8)*v11 < (unsigned int)v12[(_QWORD)v11])
         - 1);
    if ( v14 )
    {
      strncpy(Dest, *(const char **)(a2 + 24), v7);
      v15 = v10;
    }
    else
    {
      v15 = Dest;
    }
    strncpy(v10, v15, v8);
    if ( v8 < (unsigned int)v4 )
      v5 = v8;
    *(_QWORD *)(a2 + 56) = v5;
    ------
}

sub_15074函数如下:

__int64 __fastcall sub_15074(__int64 a1, IRP *a2)
{
    ------//省略部分代码
    v9 = a2->AssociatedIrp.MasterIrp;
    if ( !strcmp((const char *)v9, (const char *)qword_151F0) )
    {
      v10 = v5;
      v11 = Dst;
      v12 = (char *)v9;
    }
    else
    {
      memset(Dst, 0, 0x64ui64);
      v10 = 99i64;
      v11 = (const char *)v9;
      v12 = Dst;
    }
    strncpy(v12, v11, v10);
    if ( (unsigned int)v5 < (unsigned int)v2 )
      v7 = v5;
    a2->IoStatus.Information = v7;
    ------
}

对比可以发现,1.16版本的SSPORT.SYS驱动文件对数据拷贝函数strncpy的使用前进行了处理和限制,规定了拷贝的大小v10=99,且对传入数据作了限制。而观察1.14版本SSPORT.SYS驱动文件没有对传入数据进行任何限制,直接进行strncpy拷贝,当传入数据大小较大时,就会出现溢出的现象。

 

漏洞复现

该漏洞发生模块为SSPORT.SYS驱动模块,因此触发到该漏洞后会导致系统崩溃蓝屏现象。在Win10上安装1.14版本驱动安装程序后,传入SSPORT.SYS驱动的数据设置成超长字符数组,则会立刻触发漏洞,导致系统蓝屏。复现情况如下视频所示:

漏洞复现

 

漏洞影响

该漏洞触发后会导致系统崩溃蓝屏现象,成功利用之后可以引发非特权用户提升到SYSTEM权限,并在kernel模式下运行代码。成功利用该驱动程序漏洞可能允许攻击者安装程序、查看、更改、加密或删除数据,或者创建具有完全用户权限的新帐户。

 

漏洞修复和建议

目前该漏洞厂商已发布修复补丁,惠普和Xerox分别发布了针对该漏洞的安全更新信息HPSBPI03724XRX21K

为了缓解这个问题,用户应该使用这个链接并查找他们的打印机型号,然后下载补丁文件,进行漏洞修复。

 

参考链接

https://labs.sentinelone.com/cve-2021-3438-16-years-in-hiding-millions-of-printers-worldwide-vulnerable/

(完)