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

Out of range memory access in MbedOS CoAP library parser - option number #12926

Closed
mjurczak opened this issue May 5, 2020 · 2 comments
Closed

Comments

@mjurczak
Copy link

mjurczak commented May 5, 2020

Description of defect

References:

https://github.com/ARMmbed/mbed-os/tree/mbed-os-5.15.3/features/frameworks/mbed-coap

https://github.com/ARMmbed/mbed-coap/tree/v5.1.5

File:

sn_coap_parser.c

Example Traces:
    #0  sn_coap_parser_options_parse()
        sn_coap_parser.c:310
    #1  sn_coap_parser()
        sn_coap_parser.c:161

    #0  sn_coap_parser_options_parse()
        sn_coap_parser.c:314
    #1  sn_coap_parser()
        sn_coap_parser.c:161

Analysis:

If a packet with option delta equal to 13 or 14 is parsed with no extended option delta following, access beyond the packet data buffer is made due to insufficient message length checks:

if (option_number == 13) {
option_number = *(*packet_data_pptr + 1) + 13;
(*packet_data_pptr)++;
} else if (option_number == 14) {
if (message_left >= 2){
option_number = *(*packet_data_pptr + 2);
option_number += (*(*packet_data_pptr + 1) << 8) + 269;
(*packet_data_pptr) += 2;
} else {
/* packet_data_pptr would overflow! */
tr_error("sn_coap_parser_options_parse - **packet_data_pptr overflow !");
return -1;
}
}

Before option number processing the message left bytes is calculated including the option delta/option length byte:

message_left = packet_len - ((*packet_data_pptr) - packet_data_start_ptr);

In case of option delta set to 13, the extended delta byte is accessed in the following line without prior check for buffer out-of-bound index:

option_number = *(*packet_data_pptr + 1) + 13;

In case of option delta set to 14, the extended delta bytes are accessed with insufficient index check. As the message_left variable includes the option delta byte, the check will pass malformed frame if there is only one extended delta byte following:

} else if (option_number == 14) {
if (message_left >= 2){
option_number = *(*packet_data_pptr + 2);
option_number += (*(*packet_data_pptr + 1) << 8) + 269;

Type:

  • Integer Overflow or Wraparound
  • Out-of-bounds Read

Result:

  • Parsing data out of input bounds
  • Possible crash due out-of-bound memory access

Target(s) affected by this defect ?

  • MbedOS mbed-coap library 5.1.5
  • MbedOS 5.15.3

Toolchain(s) (name and version) displaying this defect ?

N/A

What version of Mbed-os are you using (tag or sha) ?

MbedOS 5.15.3

What version(s) of tools are you using. List all that apply (E.g. mbed-cli)

N/A

How is this defect reproduced ?

Parsing the provided input example input with sn_coap_parser() function.

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "sn_coap_protocol.h"
#include "sn_coap_header.h"

struct coap_s* coapHandle;
coap_version_e coapVersion = COAP_VERSION_1;

void* coap_malloc(uint16_t size){
    return malloc(size);
}

void coap_free(void* addr){
    free(addr);
}

uint8_t coap_tx_cb(uint8_t *arg_a, uint16_t arg_b, sn_nsdl_addr_s *arg_c, void *arg_d){
    return 0;
}

int8_t coap_rx_cb(sn_coap_hdr_s *arg_a, sn_nsdl_addr_s *arg_b, void *arg_c){
    return 0;
}

int main(int argc, const char* argv[])
{
    FILE *fp;
    size_t read_bytes;
    size_t input_size;
    uint8_t *message_buffer;
    if (argc != 2)
    {
       return 1;
    }
    
    fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
      return 2;
    }
     
    fseek (fp , 0 , SEEK_END);
    input_size = ftell(fp);
    rewind (fp);
     
    if (input_size > 65527)
    {
      return 3;
    }
     
    message_buffer = malloc(input_size);
    read_bytes = fread(message_buffer, 1, input_size, fp);
    fclose(fp);
    coapHandle = sn_coap_protocol_init(&coap_malloc, &coap_free, &coap_tx_cb, &coap_rx_cb);
    sn_coap_hdr_s* parsed = sn_coap_parser(coapHandle, read_bytes, message_buffer, &coapVersion);
    sn_coap_parser_release_allocated_coap_msg_mem(coapHandle, parsed);
    free(message_buffer);
    
    return 0;
}

sn_coap_parser.c:310__read_buffer_overflow_minimal.log
sn_coap_parser.c:314__read_buffer_overflow_minimal.log

@ciarmcom
Copy link
Member

ciarmcom commented May 6, 2020

Thank you for raising this detailed GitHub issue. I am now notifying our internal issue triagers.
Internal Jira reference: https://jira.arm.com/browse/MBOTRIAGE-2663

@mjurczak
Copy link
Author

mjurczak commented May 8, 2020

Patch proposal:

#12928 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants