View Issue Details

IDProjectCategoryView StatusLast Update
0000483fileGeneralpublic2023-12-20 21:28
Reporterpromptfuzz Assigned Tochristos  
PriorityhighSeveritycrashReproducibilityalways
Status feedbackResolutionopen 
PlatformLinuxOSUbuntuOS Version22.04
Product Version5.45 
Summary0000483: Buffer-overflow in check_buffer() (apprentice.c:3358:6)
DescriptionHi,
 I found a heap buffer overflow bug in function check_buffer() (at file apprentice.c:3358:6), triggered via the public API :
file_public int magic_load_buffers(struct magic_set *ms, void **bufs, size_t *sizes, size_t nbufs).
 
This bug can be cause an out-of-bound read issue via craft magic files.

A poc file is:
```
// poc.cc
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    magic_t magic = magic_open(MAGIC_NONE);
    if (magic == NULL) {
        return -1;
    }
    // Load buffers
    void* buffers[] = { (void*)data };
    size_t buffer_sizes[] = { size };
    if (magic_load_buffers(magic, buffers, buffer_sizes, 1) == -1) {
        // Error handling
    }
    
    magic_close(magic);
    
    return 0;
}
```

In the poc file, magic_load_buffers() will finally call `check_buffer(ms, map, "buffer")`,
where map->p = data.
In the code below, if the data is passed with length of 1 byte, the data with 1 byte lengh is cast to a type of 2 byte lengh (line 3357) first,
  and then it is accessed with 2 bytes in line 3358 where an one byte out-of-read happened.

```
check_buffer(struct magic_set *ms, struct magic_map *map, const char *dbname)
{
    uint32_t *ptr;
    uint32_t entries, nentries;
    uint32_t version;
    int i, needsbyteswap;

3357 ptr = CAST(uint32_t *, map->p);
3358. if (*ptr != MAGICNO) {
```

As magic_load_buffers() is a public API, if the buffer passed in could be controlled by remote attackers,
it might cause deny-of-services or information leaks.

I strongly suggest you add a buffer length check in check_buffer() to avoid the potential issue.
Thanks.
Steps To ReproduceFirstly, compile the libmagic with ASAN:
```
     export CC=clang
    export CXX=clang++
    SANITIZER_FLAGS="-O0 -fsanitize=address,undefined -fsanitize-address-use-after-scope -g "
    export CFLAGS="${CFLAGS:-} $SANITIZER_FLAGS"
    export CXXFLAGS="${CXXFLAGS:-} $SANITIZER_FLAGS -stdlib=libc++"

    cd $SRC/libmagic
    rm -rf build
    mkdir -p build
    autoreconf -i
    cd build
    ../configure --enable-static --enable-fsect-man5 --disable-libseccomp --disable-xzlib --disable-bzlib --disable-zlib
    make V=1 all
```

Then, compile the poc program:
clang++ -fsanitize=address -g -O0 -I/libmagic/include poc.cc -o poc.out /libmagic/lib/libmagic.a

Just run `./poc.out` is enough to reproduce this issue.
Additional Information==767084==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000090 at pc 0x5555557b502c bp 0x7fffffffcc40 sp 0x7fffffffcc38
READ of size 4 at 0x602000000090 thread T0
[Detaching after fork from child process 767104]
    #0 0x5555557b502b in check_buffer /libmagic/build/src/../../src/apprentice.c:3358:6
    0000001 0x55555578bef8 in apprentice_buf /ibmagic/build/src/../../src/apprentice.c:3262:6
    0000002 0x55555578bef8 in buffer_apprentice /libmagic/build/src/../../src/apprentice.c:713:9
    0000003 0x5555557870d7 in LLVMFuzzerTestOneInput /poc.cc:44:9
Tagsbug

Activities

christos

2023-12-20 21:28

manager   ~0003988

I moved the size checks first.

Issue History

Date Modified Username Field Change
2023-10-08 08:37 promptfuzz New Issue
2023-10-08 08:37 promptfuzz Tag Attached: bug
2023-12-20 21:28 christos Assigned To => christos
2023-12-20 21:28 christos Status new => assigned
2023-12-20 21:28 christos Status assigned => feedback
2023-12-20 21:28 christos Note Added: 0003988