Out-of-bounds Write in bfabiszewski/libmobi

Valid

Reported on

Sep 9th 2021


✍️ Description

Overview

This vulnerability is of writing user controlled values out of the buffer. The buffer is of MOBIBuffer type which is allocated using malloc. It is possible for the attacker to finally accomplish RCE (Remote Code Execution) using this out-of-bound write vulnerability to overwrite control-flow critical memory values.

Root Cause & Fix Suggestion

This vulnerability is introduced by incomplete check of buffer boundaries in mobi_buffer_move (src/buffer.c). In that function, when offset < 0, the condition buf->offset + len <= buf->maxlen doesn't be checked. Currently, that function only checks whether buf->offset >= abs(offset) when offset < 0.

The following code shows the vulnerable point and possible fix.

// src/buffer.c
void mobi_buffer_move(MOBIBuffer *buf, const int offset, const size_t len) {
    size_t aoffset = (size_t) abs(offset);
    unsigned char *source = buf->data + buf->offset;
    if (offset >= 0) {
        if (buf->offset + aoffset + len > buf->maxlen) {
            debug_print("%s", "End of buffer\n");
            buf->error = MOBI_BUFFER_END;
            return;
        }
        source += aoffset;
    } else {
        // INCOMPLETE CHECK HERE:
        // should also check buf->offset + len <= buf->maxlen
        // POSSIBLE FIX:
        // if ( (buf->offset < aoffset) || (buf->offset + len <= buf->maxlen) )
        if (buf->offset < aoffset) {
            debug_print("%s", "End of buffer\n");
            buf->error = MOBI_BUFFER_END;
            return;
        }
        source -= aoffset;
    }
    // due to the incomplete check, the memmove can out-of-bound write
    memmove(buf->data + buf->offset, source, len);
    buf->offset += len;
}

🕵️‍♂️ Proof of Concept

  • Download latest libmobi and compile it with Address Sanitizer: CFLAGS=" -fsanitize=address " CXXFLAGS=" -fsanitize=address "
  • Use the following command and this POC-FILE to reproduce the crash:
# enable address sanitizer
export ASAN_OPTIONS=abort_on_error=1:disable_coredump=0:unmap_shadow_on_exit=1
# reproduce the crash
./mobitool -cdeimsrux7 -o any-tmp-dir-path POC-FILE

You should get similar crash information as follows:

=================================================================
==14492==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x621000009d00 at pc 0x7ffff762917a bp 0x7fffffffbef0 sp 0x7fffffffb698
WRITE of size 1 at 0x621000009d00 thread T0
    #0 0x7ffff7629179 in memmove (/lib/x86_64-linux-gnu/libasan.so.6+0x3a179)
    #1 0x7ffff75857c9 in mobi_buffer_move /src/libmobi/libmobi-git/src/buffer.c:520
    #2 0x7ffff7585d83 in mobi_decompress_lz77 /src/libmobi/libmobi-git/src/compression.c:59
    #3 0x7ffff75ad161 in mobi_decompress_content /src/libmobi/libmobi-git/src/util.c:1774
    #4 0x7ffff75ad677 in mobi_dump_rawml /src/libmobi/libmobi-git/src/util.c:1856
    #5 0x5555555630e4 in dump_rawml /src/libmobi/libmobi-git/tools/mobitool.c:333
    #6 0x5555555661e3 in loadfilename /src/libmobi/libmobi-git/tools/mobitool.c:775
    #7 0x555555566e46 in main /src/libmobi/libmobi-git/tools/mobitool.c:962
    #8 0x7ffff73a90b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
    #9 0x55555555dead in _start (/src/libmobi/libmobi-git/install/bin/mobitool+0x9ead)

0x621000009d00 is located 0 bytes to the right of 4096-byte region [0x621000008d00,0x621000009d00)
allocated by thread T0 here:
    #0 0x7ffff769f517 in malloc (/lib/x86_64-linux-gnu/libasan.so.6+0xb0517)
    #1 0x7ffff75acb85 in mobi_decompress_content /src/libmobi/libmobi-git/src/util.c:1702
    #2 0x7ffff75ad677 in mobi_dump_rawml /src/libmobi/libmobi-git/src/util.c:1856
    #3 0x5555555630e4 in dump_rawml /src/libmobi/libmobi-git/tools/mobitool.c:333
    #4 0x5555555661e3 in loadfilename /src/libmobi/libmobi-git/tools/mobitool.c:775
    #5 0x555555566e46 in main /src/libmobi/libmobi-git/tools/mobitool.c:962
    #6 0x7ffff73a90b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

💥 Impact

This vulnerability is capable of overwriting memory content with user given values. For all applications using libmobi (commits 983b89820e1c592d9d7c8c438af46e75be1f96e1 in Jun 8th, 2021 or release version 0.6 (2020 Aug 1st)) It is possible for the attacker to finally accomplish RCE (Remote Code Execution) using this out-of-bound write vulnerability to overwrite control-flow critical memory values.

We created a GitHub Issue asking the maintainers to create a SECURITY.md a year ago
Cen Zhang submitted a
a year ago
Cen Zhang
a year ago

Researcher


The developer has confirmed and accepted the patch.

Cen Zhang
a year ago

Researcher


Hi, may you assign a CVE for this?

Cen Zhang
a year ago

Researcher


@admin

Bartek Fabiszewski validated this vulnerability a year ago
Cen Zhang has been awarded the disclosure bounty
The fix bounty is now up for grabs
Bartek Fabiszewski confirmed that a fix has been merged on ab5bf0 a year ago
Cen Zhang has been awarded the fix bounty
buffer.c#L513-L520 has been validated
Cen Zhang
a year ago

Researcher


@admin sorry to bother again, may I know can we have a CVE for this? Thanks~

Jamie Slome
a year ago

Admin


@occia - we will get this sorted for you now!

Jamie Slome
a year ago

Admin


CVE published! 🎉

It should be made available in the National Vulnerability Database shortly.

Ref: CVE-2021-3751

Cen Zhang
a year ago

Researcher


thanks!

to join this conversation