Skip to content
Snippets Groups Projects
  1. Jan 24, 2015
  2. Jan 23, 2015
    • Petteri Aimonen's avatar
      Fix encoded_size #defines for oneof messages. · d32d04ba
      Petteri Aimonen authored
      The sizes are represented as EncodedSize() instances, which cause
      max() operation to sort them by address instead of value. This caused
      pretty much random item to be selected for the maximum.
      
      Update issue 141
      Status: FixedInGit
      d32d04ba
  3. Jan 15, 2015
  4. Jan 11, 2015
  5. Jan 07, 2015
  6. Jan 05, 2015
  7. Jan 04, 2015
  8. Jan 03, 2015
  9. Dec 26, 2014
  10. Dec 22, 2014
  11. Sep 16, 2014
  12. Sep 11, 2014
    • Petteri Aimonen's avatar
      Publishing nanopb-0.3.1 · b947dc6e
      Petteri Aimonen authored
      nanopb-0.3.1
      b947dc6e
    • Petteri Aimonen's avatar
      Update changelog · 8d7deb49
      Petteri Aimonen authored
      8d7deb49
    • Petteri Aimonen's avatar
    • Petteri Aimonen's avatar
      Protect against size_t overflows in pb_dec_bytes/pb_dec_string. · d2099cc8
      Petteri Aimonen authored
      Possible consequences of bug:
      1) Denial of service by causing a crash
         Possible when all of the following apply:
            - Untrusted data is passed to pb_decode()
            - The top-level message contains a static string field as the first field.
         Causes a single write of '0' byte to 1 byte before the message struct.
      
      2) Remote code execution
         Possible when all of the following apply:
            - 64-bit platform
            - The message or a submessage contains a static/pointer string field.
            - Decoding directly from a custom pb_istream_t
            - bytes_left on the stream is set to larger than 4 GB
         Causes a write of up to 4 GB of data past the string field.
      
      3) Possible heap corruption or remote code execution
         Possible when all of the following apply:
            - less than 64-bit platform
            - The message or a submessage contains a pointer-type bytes field.
         Causes a write of sizeof(pb_size_t) bytes of data past a 0-byte long
         malloc()ed buffer. On many malloc() implementations, this causes at
         most a crash. However, remote code execution through a controlled jump
         cannot be ruled out.
      
      --
      
      Detailed analysis follows
      
      In the following consideration, I define "platform bitness" as equal to
      number of bits in size_t datatype. Therefore most 8-bit platforms are
      regarded as 16-bit for the purposes of this discussion.
      
      1. The overflow in pb_dec_string
      
      The overflow happens in this computation:
      
      uint32_t size;
      size_t alloc_size;
      alloc_size = size + 1;
      
      There are two ways in which the overflow can occur: In the uint32_t
      addition, or in the cast to size_t. This depends on the platform
      bitness.
      
      On 32- and 64-bit platforms, the size has to be UINT32_MAX for the
      overflow to occur. In that case alloc_size will be 0.
      
      On 16-bit platforms, overflow will happen whenever size is more than
      UINT16_MAX, and resulting alloc_size is attacker controlled.
      
      For static fields, the alloc_size value is just checked against the
      field data size. For pointer fields, the alloc_size value is passed to
      malloc(). End result in both cases is the same, the storage is 0 or
      just a few bytes in length.
      
      On 16-bit platforms, another overflow occurs in the call to pb_read(),
      when passing the original size. An attacker will want the passed value
      to be larger than the alloc_size, therefore the only reasonable choice
      is to have size = UINT16_MAX and alloc_size = 0. Any larger multiple
      will truncate to the same values.
      
      At this point we have read atleast the tag and the string length of the
      message, i.e. atleast 3 bytes. The maximum initial value for stream
      bytes_left is SIZE_MAX, thus at this point at most SIZE_MAX-3 bytes are
      remaining.
      
      On 32-bit and 16-bit platforms this means that the size passed to
      pb_read() is always larger than the number of remaining bytes. This
      causes pb_read() to fail immediately, before reading any bytes.
      
      On 64-bit platforms, it is possible for the bytes_left value to be set
      to a value larger than UINT32_MAX, which is the wraparound point in
      size calculation. In this case pb_read() will succeed and write up to 4
      GB of attacker controlled data over the RAM that comes after the string
      field.
      
      On all platforms, there is an unconditional write of a terminating null
      byte. Because the size of size_t typically reflects the size of the
      processor address space, a write at UINT16_MAX or UINT32_MAX bytes
      after the string field actually wraps back to before the string field.
      Consequently, on 32-bit and 16-bit platforms, the bug causes a single
      write of '0' byte at one byte before the string field.
      
      If the string field is in the middle of a message, this will just
      corrupt other data in the message struct. Because the message contents
      is attacker controlled anyway, this is a non-issue. However, if the
      string field is the first field in the top-level message, it can
      corrupt other data on the stack/heap before it. Typically a single '0'
      write at a location not controlled by attacker is enough only for a
      denial-of-service attack.
      
      When using pointer fields and malloc(), the attacker controlled
      alloc_size will cause a 0-size allocation to happen. By the same logic
      as before, on 32-bit and 16-bit platforms this causes a '0' byte write
      only. On 64-bit platforms, however, it will again allow up to 4 GB of
      malicious data to be written over memory, if the stream length allows
      the read.
      
      2. The overflow in pb_dec_bytes
      
      This overflow happens in the PB_BYTES_ARRAY_T_ALLOCSIZE macro:
      
      The computation is done in size_t data type this time. This means that
      an overflow is possible only when n is larger than SIZE_MAX -
      offsetof(..). The offsetof value in this case is equal to
      sizeof(pb_size_t) bytes.
      
      Because the incoming size value is limited to 32 bits, no overflow can
      happen here on 64-bit platforms.
      
      The size will be passed to pb_read(). Like before, on 32-bit and 16-bit
      platforms the read will always fail before writing anything.
      
      This leaves only the write of bdest->size as exploitable. On statically
      allocated fields, the size field will always be allocated, regardless
      of alloc_size. In this case, no buffer overflow is possible here, but
      user code could possibly use the attacker controlled size value and
      read past a buffer.
      
      If the field is allocated through malloc(), this will allow a write of
      sizeof(pb_size_t) attacker controlled bytes to past a 0-byte long
      buffer. In typical malloc implementations, this will either fit in
      unused alignment padding area, or cause a heap corruption and a crash.
      Under very exceptional situation it could allow attacker to influence
      the behaviour of malloc(), possibly jumping into an attacker-controlled
      location and thus leading to remote code execution.
      d2099cc8
    • Petteri Aimonen's avatar
      Add just-to-be-sure check to allocate_field(). · d0466bdf
      Petteri Aimonen authored
      This check will help to detect bugs earlier, and is quite lightweight
      compared to malloc() anyway.
      d0466bdf
    • Petteri Aimonen's avatar
      Fix memory leak with duplicated fields and PB_ENABLE_MALLOC. · 5e3edb54
      Petteri Aimonen authored
      If a required or optional field appeared twice in the message data,
      pb_decode will overwrite the old data with new one. That is fine, but
      with submessage fields, it didn't release the allocated subfields before
      overwriting.
      
      This bug can manifest if all of the following conditions are true:
      
      1. There is a message with a "optional" or "required" submessage field
         that has type:FT_POINTER.
      
      2. The submessage contains atleast one field with type:FT_POINTER.
      
      3. The message data to be decoded has the submessage field twice in it.
      5e3edb54
    • Petteri Aimonen's avatar
      Fix crash in pb_release() if called twice on same message. · 13a07e35
      Petteri Aimonen authored
      There was a double-free bug in pb_release() because it didn't set size fields
      to zero after deallocation. Most commonly this happens if pb_decode() fails,
      internally calls pb_release() and then application code also calls pb_release().
      13a07e35
    • Petteri Aimonen's avatar
      Add a better fuzz test. · 0dce9ef6
      Petteri Aimonen authored
      Attempts to verify all the properties defined in the security model,
      while also being portable and able to run on many platforms.
      0dce9ef6
  13. Sep 07, 2014
Loading