Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

buffer overflow in USBDevice #28

Open
hac425xxx opened this issue Jun 9, 2021 · 6 comments
Open

buffer overflow in USBDevice #28

hac425xxx opened this issue Jun 9, 2021 · 6 comments
Labels
bug Something isn't working

Comments

@hac425xxx
Copy link

bug 1 - buffer overflow in USBD_CtrlReceiveData

path

Device/usbd_ctrl.c

code

 
USBD_ReturnType USBD_CtrlReceiveData(USBD_HandleType *dev, void *data)
{
    USBD_ReturnType retval = USBD_E_ERROR;

    /* Sanity check */
    if (dev->EP.OUT[0].State == USB_EP_STATE_SETUP)
    {
        uint16_t len = dev->Setup.Length;  // recv from other USB device.

        dev->EP.OUT[0].State = USB_EP_STATE_DATA;
        USBD_PD_EpReceive(dev, 0x00, (uint8_t*)data, len);

        retval = USBD_E_OK;
    }
    return retval;
}

dev->Setup.Length is recv from other USB device, if dev->Setup.Length > the size of data, it will overflow.

@hac425xxx
Copy link
Author

hac425xxx commented Jun 9, 2021

bug 2 - out of bound read and buffer overflow in dfu_upload

path

Class/DFU/usbd_dfu.c

code

static USBD_ReturnType dfu_upload(USBD_DFU_IfHandleType *itf)
{

    USBD_HandleType *dev = itf->Base.Device;


    if ((dev->Setup.Length > 0) && (DFU_APP(itf)->Read != NULL))
    {

        /* Read memory */
        else if (itf->BlockNum > 1)
        {
            itf->DevStatus.State = DFU_STATE_UPLOAD_IDLE;

            DFU_APP(itf)->Read(
                    DFUSE_GETADDRESS(itf, &dfu_desc),
                    data,
                    dev->Setup.Length);   // bug !!!

            retval = USBD_CtrlSendData(dev, data, dev->Setup.Length);
        }

if dev->Setup.Length is too large, it could lead out of bound read, or overflow

case 2

        /* Check for correct sequence */
        if (dev->Setup.Value == ((itf->BlockNum + 1) & 0xFFFF))
        {
            uint16_t len;
            uint32_t progress = (uint32_t)itf->Address - DFU_APP(itf)->Firmware.Address;

            /* Shorten the block size if it's the end of the firmware memory,
             * return to IDLE */
            if ((progress + dev->Setup.Length) > DFU_APP(itf)->Firmware.TotalSize)
            {
                len = DFU_APP(itf)->Firmware.TotalSize - progress;
                itf->DevStatus.State = DFU_STATE_IDLE;
            }
            else
            {
                len = dev->Setup.Length;
                itf->DevStatus.State = DFU_STATE_UPLOAD_IDLE;
            }

            DFU_APP(itf)->Read(itf->Address, data, len);

it could check dev->Setup.Length with Firmware.TotalSize.

(progress + dev->Setup.Length) > DFU_APP(itf)->Firmware.TotalSize

the length of data is 256 bytes, but Firmware.TotalSize is more large than 256, such as 24568

make TARGET_HEADER="\<stm32f042x6.h\>" SERIES=STM32F0 APP_ADDRESS=0x08002000 APP_SIZE=24568 TOTAL_ERASE_MS=480 VID=FFFF PID=FFFF

it could lead buffer overflow when read data to data.

DFU_APP(itf)->Read(itf->Address, data, len);

@hac425xxx
Copy link
Author

bug 3- buffer overflow in dfu_download

path

Class/DFU/usbd_dfu.c

code

            /* Checks for valid sequence and overall length */
            if (   ( dev->Setup.Value == ((itf->BlockNum + 1) & 0xFFFF))
                && (((uint32_t)itf->Address + dev->Setup.Length) <
                    (DFU_APP(itf)->Firmware.Address + DFU_APP(itf)->Firmware.TotalSize)))

            {
                
                /* Prepare the reception of the buffer over EP0 */
                retval = USBD_CtrlReceiveData(dev, dev->CtrlData);
            }

it could check dev->Setup.Length with Firmware.TotalSize, but Firmware.TotalSize is more large than the length of data

@benedekkupper
Copy link
Member

Thanks for this analysis, I have provided fixes that should remedy these exploitable bugs. Please keep me updated with newer results. Just out of curiosity, what tool are you using to analyze the code?

@hac425xxx
Copy link
Author

I analyze the code by vscode.

these patch seems ok.

I also have a question

                /* HID report OUT */
                case HID_REQ_SET_REPORT:
                {
                    uint16_t max_len;
                    if (reportType == HID_REPORT_OUTPUT)
                    {
                        max_len = HID_APP(itf)->Report->Output.MaxSize;
                    }
                    else
                    {
                        max_len = HID_APP(itf)->Report->Feature.MaxSize;
                    }
                    retval = USBD_CtrlReceiveData(dev, dev->CtrlData, max_len);
                    break;
                }

Where is the .MaxSize field defined?

@benedekkupper
Copy link
Member

Those are defined by the author of the application, as part of a const struct.

@hac425xxx
Copy link
Author

ok, and do we need to verify that MaxSize smaller than the size of CtrlData?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants