Project: sleuthkit (sleuthkit/sleuthkit), language: c++
Vulnerability instance: sleuthkit.cve-2018-11738
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/sleuthkit/sleuthkit/issues/1265
## Description:
Issue: sleuthkit/sleuthkit#1265
Title: AddressSanitizer: out-of-bounds read (OOB) in ntfs_make_data_run (tsk/fs/ntfs.c:591:12)
State: open
Created by: glen-mac
Created at: 2018-06-03 13:31:44+00:00

Issue Body:
Hey there, I have discovered an out-of-bounds read in the sleuth kit at: [ntfs.c:591:12](https://github.com/sleuthkit/sleuthkit/blob/4efa611df63e627f7850b10b8f7eda36787dbc94/tsk/fs/ntfs.c#L591)

Found when fuzzing commit 4efa611df63e627f7850b10b8f7eda36787dbc94.

Compile flags to reproduce: 
```
CC=clang CXX=clang++ CFLAGS='-fsanitize=address -g -O2 -fno-omit-frame-pointer' CXXFLAGS=$CFLAGS make
```

System information:
```
$ uname -a
Linux s127422 3.13.0-137-generic #186-Ubuntu SMP Mon Dec 4 19:09:19 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
```

This bug was found to be in sleuth kit releases from [4.0.1](https://github.com/sleuthkit/sleuthkit/tree/sleuthkit-4.0.1) up until and including the latest release [4.6.1](https://github.com/sleuthkit/sleuthkit/tree/sleuthkit-4.6.1)

You can find a collection of PoC files that trigger the bug [here](https://github.com/sleuthkit/sleuthkit/files/2065627/ntfs1_crashes.zip)

The full ASAN report is shown below:
```
↳ tools/fstools/fls -lrp crash.file
=================================================================
==26676==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6190000270b8 at pc 0x0000006620e8 bp 0x7fff9bbf5fe0 sp 0x7fff9bbf5fd8
READ of size 1 at 0x6190000270b8 thread T0
    #0 0x6620e7 in ntfs_make_data_run /home/glenn/temp/sleuthkit/tsk/fs/ntfs.c:591:12
    #1 0x5f6a3b in ntfs_load_bmap /home/glenn/temp/sleuthkit/tsk/fs/ntfs.c:3062:10
    #2 0x5f6a3b in ntfs_open /home/glenn/temp/sleuthkit/tsk/fs/ntfs.c:5200
    #3 0x51f81b in tsk_fs_open_img /home/glenn/temp/sleuthkit/tsk/fs/fs_open.c:124:28
    #4 0x4ef892 in main /home/glenn/temp/sleuthkit/tools/fstools/fls.cpp:267:19
    #5 0x7fe550ee682f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
    #6 0x41a008 in _start (/home/glenn/temp/sleuthkit/results-binaries/fls-sleuthkit-4.6.1+0x41a008)

AddressSanitizer can not describe address in more detail (wild memory access suspected).
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/glenn/temp/sleuthkit/tsk/fs/ntfs.c:591:12 in ntfs_make_data_run
Shadow bytes around the buggy address:
  0x0c327fffcdc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffcdd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffcde0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffcdf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffce00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c327fffce10: fa fa fa fa fa fa fa[fa]fa fa fa fa fa fa fa fa
  0x0c327fffce20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffce30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffce40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffce50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c327fffce60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==26676==ABORTING
```


Comments:
Comment by FIOpwK on 2019-07-08 05:43:36+00:00:
CVE-2018-11738 was assigned to this issue (not requested by me)

Attachments:
https://github.com/sleuthkit/sleuthkit/files/2065627/ntfs1_crashes.zip

Commit References:
4efa611df63e627f7850b10b8f7eda36787dbc94

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
export CFLAGS="$CFLAGS -Wno-error=non-c-typedef-for-linkage"
export CXXFLAGS="$CXXFLAGS -Wno-error=non-c-typedef-for-linkage"
./bootstrap
./configure --enable-static --disable-shared --disable-java
make -j$(nproc)

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool
RUN git clone https://github.com/sleuthkit/sleuthkit sleuthkit
RUN git -C sleuthkit checkout 9b776576aa6a1fbf328e82fd7cb6b428179de016
WORKDIR $SRC/sleuthkit
COPY build.sh $SRC/

Additional files:
filename: sleuthkit_fls_fuzzer.cc
content: // Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stddef.h>
#include <stdint.h>

#include "sleuthkit/tsk/tsk_tools_i.h"
#include "sleuthkit_mem_img.h"

#ifndef FSTYPE
#error Define FSTYPE as a valid value of TSK_FS_TYPE_ENUM.
#endif

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  TSK_IMG_INFO *img;
  TSK_FS_INFO *fs;

  img = mem_open(data, size);
  if (img == nullptr)
    return 0;

  fs = tsk_fs_open_img(img, 0, FSTYPE);
  if (fs != nullptr) {
    tsk_fs_fls(fs, TSK_FS_FLS_FULL, fs->root_inum, TSK_FS_DIR_WALK_FLAG_RECURSE,
               nullptr, 0);

    fs->close(fs);
  }

  img->close(img);
  return 0;
}

filename: sleuthkit_mem_img.h
content: // Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef MEM_IMG_H
#define MEM_IMG_H

#include <stddef.h>
#include <stdint.h>

#include "sleuthkit/tsk/tsk_tools_i.h"

typedef struct {
  TSK_IMG_INFO img_info;
  const uint8_t *data;
  size_t size;
} IMG_MEM_INFO;

static ssize_t mem_read(TSK_IMG_INFO *img_info, TSK_OFF_T offset, char *buf,
                        size_t len) {
  IMG_MEM_INFO *mem_info = reinterpret_cast<IMG_MEM_INFO *>(img_info);
  // Bounds-checking exists in the real drivers.
  if (offset > mem_info->size) {
    return -1;
  }
  ssize_t read_len = len;
  if (offset + len > mem_info->size) {
    read_len = mem_info->size - offset;
  }
  if (memcpy(buf, mem_info->data + offset, read_len) == nullptr) {
    return -1;
  } else {
    return read_len;
  }
}

static void mem_close(TSK_IMG_INFO *img_info) {
  IMG_MEM_INFO *mem_info = reinterpret_cast<IMG_MEM_INFO *>(img_info);
  tsk_deinit_lock(&(img_info->cache_lock));
  free(mem_info);
}

static void mem_imgstat(TSK_IMG_INFO *img_info, FILE *hFile) {}

TSK_IMG_INFO *mem_open(const uint8_t *data, size_t size) {
  IMG_MEM_INFO *inmemory_img =
      reinterpret_cast<IMG_MEM_INFO *>(malloc(sizeof(IMG_MEM_INFO)));
  TSK_IMG_INFO *img;
  if (inmemory_img == nullptr) {
    return nullptr;
  }
  img = reinterpret_cast<TSK_IMG_INFO *>(inmemory_img);
  img->itype = TSK_IMG_TYPE_RAW;
  img->read = mem_read;
  img->close = mem_close;
  img->imgstat = mem_imgstat;
  img->size = size;
  img->sector_size = 512;
  tsk_init_lock(&(img->cache_lock));
  inmemory_img->data = data;
  inmemory_img->size = size;
  return img;
}

#endif // # MEM_IMG_H

filename: sleuthkit_mmls_fuzzer.cc
content: // Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stddef.h>
#include <stdint.h>

#include "sleuthkit/tsk/tsk_tools_i.h"
#include "sleuthkit_mem_img.h"

#ifndef VSTYPE
#error Define VSTYPE as a valid value of TSK_VS_TYPE_ENUM.
#endif

static TSK_WALK_RET_ENUM part_act(TSK_VS_INFO *vs, const TSK_VS_PART_INFO *part,
                                  void *ptr) {
  return TSK_WALK_CONT;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  TSK_IMG_INFO *img;
  TSK_VS_INFO *vs;

  img = mem_open(data, size);
  if (img == nullptr)
    return 0;

  vs = tsk_vs_open(img, 0, VSTYPE);
  if (vs != nullptr) {
    tsk_vs_part_walk(vs, 0, vs->part_count - 1, TSK_VS_PART_FLAG_ALL, part_act,
                     nullptr);

    tsk_vs_close(vs);
  }

  img->close(img);
  return 0;
}