[하루한줄] CVE-2021-3438: Samsung,HP 프린터 드라이버의 Buffer Overflow 취약점

URL

Root Cause Analysis of a Printer’s Drivers Vulnerability CVE-2021-3438

Target

  • Samsung, HP, Xerox

Explain

Samsung, HP, Xerox 사에서 16년 전 배포된 프린터 드라이버에서 버퍼 오버플로우 취약점이 발견되었습니다.

취약점은 프린터의 핵심 구성 요소인 Serial Port Driver SSPORT.sys 의 IOCTL 0x9C402408 루틴에 존재합니다.

char GlobalBuffer[4096];
NTSTATUS SioctlDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    NTSTATUS status = STATUS_SUCCESS;
    size_t datalen = strlen("This String is from Device Driver@@@@@ !!!") + 1;
    PIO_STACK_LOCATION irpSP = IoGetCurrentIrpStackLocation(Irp);
    ULONG inBufLength = irpSP->Parameters.DeviceIoControl.InputBufferLength;
    ULONG outBufLength = irpSP->Parameters.DeviceIoControl.OutputBufferLength;
    if (!inBufLength || !outBufLength) {
        status = STATUS_INVALID_PARAMETER;
        goto End;
    }
    switch (irpSP->Parameters.DeviceIoControl.IoControlCode) {
        case 0x9C402408: // CTL_CODE(40000, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS)
        {
            char* inBuf = (char*)Irp->AssociatedIrp.SystemBuffer;
            char* outBuf = (char*)Irp->AssociatedIrp.SystemBuffer;
            if (strcmp(inBuf, "AA"))
            {
                strncpy(GlobalBuffer, inBuf, inBufLength); //Vulnerability
            }
            else
            {
                inBuf = GlobalBuffer;
            }
            strncpy(outBuf, inBuf, outBufLength);
            Irp->IoStatus.Information = outBufLength < datalen ? outBufLength : datalen; 
            break; 
        } 
        case 0x9C402401: // CTL_CODE(40000, 0x900, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
        case 0x9C402406: // CTL_CODE(40000, 0x901, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
        case 0x9C40240F: // CTL_CODE(40000, 0x903, METHOD_NEITHER, FILE_ANY_ACCESS) 
            break; 
        default: 
            status = STATUS_INVALID_DEVICE_REQUEST; 
            break;
    } 
End: 
    Irp->IoStatus.Status = status;
    IofCompleteRequest(Irp, 0);
    return status;
}

strncpy 함수에서 inBuf의 값을 inBufLength의 크기만큼 GlobalBuffer에 복사합니다. 이 때 inBufinBufLength 값을 IOCTL 요청시 UserBuffer 에 따라 임의의 값으로 설정할 수 있습니다. 따라서 .data 섹션에 정의된 4096 크기의 GlobalBuffer를 넘어 .pdata 섹션까지 덮어쓸 수 있습니다.

그러나 제어 가능한 섹션이 읽기 전용으로 설정되어 로컬 서비스 거부(Dos) 외의 유효한 공격 벡터는 발견되지 않았으며, 해당 드라이버가 배포된 2005년 이후 취약점이 악용되지는 않은 것으로 알려졌습니다.