Project: libical (libical/libical), language: c++
Vulnerability instance: libical.cve-2016-5824
Sanitizer: address

================= Bug Report (1/3) ==================
## Source: GitHub Issue
## URL: https://github.com/libical/libical/issues/235
## Description:
Issue: libical/libical#235
Title: Potentially security-sensitive crashes, best way to get them to you?
State: closed
Created by: brandonprry
Created at: 2016-05-22 19:42:45+00:00

Issue Body:
Hello,

I have been fuzzing libical for a while, I have a handful of use-after-frees (might be all the same root bug) I would like to provide, but these are potentially security-sensitive and not appropriate for a github comment.

An example asan trace (tested against 1.0, 1.0.1?, and master from 20 minutes ago):

```
=================================================================
==19414==ERROR: AddressSanitizer: heap-use-after-free on address 0x60200000e8f5 at pc 0x7fc4d2ffc649 bp 0x7ffda2a4b8c0 sp 0x7ffda2a4b038
READ of size 1 at 0x60200000e8f5 thread T0
    #0 0x7fc4d2ffc648  (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x60648)
    #1 0x7fc4d2ffd5a5 in __interceptor_vsnprintf (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x615a5)
    #2 0x7fc4d2ffd811 in snprintf (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x61811)
    #3 0x7fc4d2d6fb30 in icalreqstattype_as_string_r (/root/libical_asan/build/lib/libical.so.2+0x4fb30)
    #4 0x7fc4d2d7247b in icalvalue_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x5247b)
    #5 0x7fc4d2d6108c in icalproperty_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x4108c)
    #6 0x7fc4d2d57132 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x37132)
    #7 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #8 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #9 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #10 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #11 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #12 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #13 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #14 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #15 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #16 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #17 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #18 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #19 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #20 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #21 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #22 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #23 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #24 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #25 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #26 0x7fc4d2d571a3 in icalcomponent_as_ical_string_r (/root/libical_asan/build/lib/libical.so.2+0x371a3)
    #27 0x7fc4d2d56fd1 in icalcomponent_as_ical_string (/root/libical_asan/build/lib/libical.so.2+0x36fd1)
    #28 0x400cd4 in main (/root/libical_asan/build/src/test/parser+0x400cd4)
    #29 0x7fc4d2976a3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x20a3f)
    #30 0x400ae8 in _start (/root/libical_asan/build/src/test/parser+0x400ae8)

0x60200000e8f5 is located 5 bytes inside of 6-byte region [0x60200000e8f0,0x60200000e8f6)
freed by thread T0 here:
    #0 0x7fc4d30346aa in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x986aa)
    #1 0x7fc4d2d5c667 in icalmemory_free_buffer (/root/libical_asan/build/lib/libical.so.2+0x3c667)
    #2 0x7fc4d2d600d7 in icalparser_add_line (/root/libical_asan/build/lib/libical.so.2+0x400d7)
    #3 0x400cbd in main (/root/libical_asan/build/src/test/parser+0x400cbd)
    #4 0x7fc4d2976a3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x20a3f)

previously allocated by thread T0 here:
    #0 0x7fc4d30349aa in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x989aa)
    #1 0x7fc4d2d5c5d3 in icalmemory_new_buffer (/root/libical_asan/build/lib/libical.so.2+0x3c5d3)
    #2 0x7fc4d2d5e44c in make_segment (/root/libical_asan/build/lib/libical.so.2+0x3e44c)
    #3 0x7fc4d2d5e82d in icalparser_get_value (/root/libical_asan/build/lib/libical.so.2+0x3e82d)
    #4 0x7fc4d2d5feb6 in icalparser_add_line (/root/libical_asan/build/lib/libical.so.2+0x3feb6)
    #5 0x400cbd in main (/root/libical_asan/build/src/test/parser+0x400cbd)
    #6 0x7fc4d2976a3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x20a3f)

SUMMARY: AddressSanitizer: heap-use-after-free ??:0 ??
Shadow bytes around the buggy address:
  0x0c047fff9cc0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd
  0x0c047fff9cd0: fa fa 00 06 fa fa fd fd fa fa 00 05 fa fa fd fd
  0x0c047fff9ce0: fa fa 00 06 fa fa fd fd fa fa fd fd fa fa 00 00
  0x0c047fff9cf0: fa fa fd fd fa fa 00 03 fa fa fd fd fa fa 00 03
  0x0c047fff9d00: fa fa fd fd fa fa 00 fa fa fa 00 07 fa fa fd fd
=>0x0c047fff9d10: fa fa fd fa fa fa fd fa fa fa fd fa fa fa[fd]fa
  0x0c047fff9d20: fa fa fd fd fa fa 03 fa fa fa fd fa fa fa fd fd
  0x0c047fff9d30: fa fa 05 fa fa fa fd fa fa fa fd fd fa fa 02 fa
  0x0c047fff9d40: fa fa fd fa fa fa 06 fa fa fa fd fd fa fa fd fa
  0x0c047fff9d50: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
  0x0c047fff9d60: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd 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
==19414==ABORTING
```

What's the best way to get the test cases to reproduce the issues to you? My email is bperry.volatile@gmail.com if you would like to hit me up directly at your convenience.



Comments:
Comment by brandonprry on 2016-05-25 02:29:40+00:00:
Re-opened here

https://bugzilla.mozilla.org/show_bug.cgi?id=1275400


================= Bug Report (2/3) ==================
## Source: GitHub Issue
## URL: https://github.com/libical/libical/issues/251
## Description:
Issue: libical/libical#251
Title: A heap-buffer-overflow in icaltime_from_string
State: closed
Created by: agustinmista
Created at: 2016-12-02 14:33:52+00:00

Issue Body:
Hello, we recently found a memory issue parsing and executing fuzzed ical file in last revision of libical (#19acf43794ad4c99f7e6687cb39424a82b737828).
We tested this issue on Ubuntu 14.04 but other configurations could be affected.
Technical details about the issue are:

```
==8557==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300000caa3 at pc 0x7ffff7b187ce bp 0x7fffffff87f0 sp 0x7fffffff87e8
READ of size 1 at 0x60300000caa3 thread T0
```

gdb backtrace is as follows:

```
#0  0x00007ffff61cfc37 in __GI_raise (sig=sig@entry=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff61d3028 in __GI_abort () at abort.c:89
#2  0x00000000004b12b6 in __sanitizer::Abort() ()
#3  0x00000000004a1f97 in __asan::AsanDie() ()
#4  0x00000000004a89cf in __sanitizer::Die() ()
#5  0x00000000004a062b in __asan::ScopedInErrorReport::~ScopedInErrorReport() ()
#6  0x00000000004a0171 in __asan_report_error ()
#7  0x00000000004a0db7 in __asan_report_load1 ()
#8  0x00007ffff7b187ce in icaltime_from_string (str=<optimized out>)
    at /home/agustin/Code/libical/src/libical/icaltime.c:448
#9  0x00007ffff7b5756f in icalvalue_new_from_string_with_error (kind=<optimized out>, 
    str=<optimized out>, error=<optimized out>)
    at /home/agustin/Code/libical/src/libical/icalvalue.c:637
#10 0x00007ffff7b548db in icalvalue_new_from_string (kind=ICAL_DATETIME_VALUE, 
    str=0x60300000ca90 "18640529T011608z")
    at /home/agustin/Code/libical/src/libical/icalvalue.c:756
#11 0x00007ffff7ad080a in icalparser_add_line (parser=<optimized out>, 
    line=<optimized out>) at /home/agustin/Code/libical/src/libical/icalparser.c:1147
#12 0x00000000004b8c3f in main (argc=2, argv=0x7fffffffdf08)
    at /home/agustin/Code/libical/src/test/icaltestparser.c:104
```

This issue was found using QuickFuzz, the file to reproduce it is [attached](https://github.com/libical/libical/files/627371/heap-buffer-overflow.ical.txt).
Regards.


Comments:
Comment by ksmurchison on 2016-12-02 15:02:46+00:00:
Can you attach icaltestparser.c so I don't have to write my own test harness?  I believe I already have a fix for this.

---

Comment by ksmurchison on 2016-12-02 15:03:38+00:00:
Never mind.  I didn't realize you were using the harness in libical

---

Comment by ksmurchison on 2016-12-02 15:23:12+00:00:
Proposed patch:

diff --git a/src/libical/icaltime.c b/src/libical/icaltime.c
index ca64763..4077ce7 100644
--- a/src/libical/icaltime.c
+++ b/src/libical/icaltime.c
@@ -445,7 +445,7 @@ struct icaltimetype icaltime_from_string(const char *str)
         tt.is_utc = 0;
         tt.is_date = 0;
     } else if ((size == 16) || (size == 20)) {  /* UTC time, ends in 'Z' */
-        if ((str[15] != 'Z') && (str[19] != 'Z'))
+        if ((str[size-1] != 'Z'))
             goto FAIL;
 
         tt.is_utc = 1;



---

Comment by agustinmista on 2016-12-02 15:28:54+00:00:
Markdown seems to have mangled your patch, can you please fix it?

---

Comment by ksmurchison on 2016-12-02 15:29:53+00:00:
[icaltime.c.diff.txt](https://github.com/libical/libical/files/627525/icaltime.c.diff.txt)


---

Comment by winterz on 2016-12-02 17:16:35+00:00:
verified that Ken's patch fixes the overflow. but now we get stuck in an infinite loop in icalparser

```
               /* Find the last colon in the line */
                do {
                    nextColon = parser_get_next_char(':', nextColon, 1);

                    if (nextColon) {
                        lastColon = nextColon;
                    }
                } while (nextColon);

```

---

Comment by ksmurchison on 2016-12-02 17:39:58+00:00:
[icalparser.c.diff.txt](https://github.com/libical/libical/files/627840/icalparser.c.diff.txt)


---

Comment by ksmurchison on 2016-12-02 17:49:59+00:00:
This fixes the infinite loop.  Note that icaltestparser.c leaks the parsed component(s) (verified by Valgrind)

---

Comment by ksmurchison on 2016-12-02 18:28:24+00:00:
I just committed a fix to icaltestparser.c that fixes the stuff that it was leaking directly.  A component is still being leaked when the iCalendar is incomplete/bogus.  Still tracking this one down.

Should I commit my icaltime.c and icalparser.c fixes?

---

Comment by winterz on 2016-12-02 19:10:17+00:00:
yes please commit.  And you can close this issue too.

---

Comment by ksmurchison on 2016-12-02 19:15:53+00:00:
Fixed with commits:
https://github.com/libical/libical/commit/38757abb495ea6cb40faa5418052278bf75040f7
https://github.com/libical/libical/commit/04d84749e53db08c71ed0ce8b6ba5c11082743cd

---

Comment by winterz on 2016-12-02 19:21:06+00:00:
hehe.. I see the leak and coverity had found it previously.  and I cheated and added a  /* coverity[leaked_storage] */ comment so Coverity wouldn't complain.  yeah, if you nice if you can fix that leak.

---

Comment by ksmurchison on 2016-12-02 20:06:34+00:00:
The leak wasn't where you thought.  It was easy to find once I compiled a debug version of libical (I was guessing before)

https://github.com/libical/libical/commit/830d9530817516377c2bc3b532798ce2c6b4765a

---

Comment by rhertzog on 2017-01-27 11:06:34+00:00:
Just to cross-reference data, this is supposed to be CVE-2016-5824 that was also reported to mozilla: https://bugzilla.mozilla.org/show_bug.cgi?id=1275400

This is according to http://www.openwall.com/lists/oss-security/2017/01/20/16

Attachments:
https://github.com/libical/libical/files/627525/icaltime.c.diff.txt
https://github.com/libical/libical/files/627840/icalparser.c.diff.txt
https://github.com/libical/libical/files/627371/heap-buffer-overflow.ical.txt

Commit References:
830d9530817516377c2bc3b532798ce2c6b4765a
38757abb495ea6cb40faa5418052278bf75040f7
04d84749e53db08c71ed0ce8b6ba5c11082743cd
19acf43794ad4c99f7e6687cb39424a82b737828

================= Bug Report (3/3) ==================
## Source: GitHub Issue
## URL: https://github.com/libical/libical/issues/286
## Description:
Issue: libical/libical#286
Title: CVE-2016-5824: use-after-free issues
State: closed
Created by: rhertzog
Created at: 2017-01-20 11:39:03+00:00

Issue Body:
@brandonprry has been fuzzing libical last year and found some issues, he reported them first in #235 but closed the ticket when he opened the same ticket against thunderbird in the hope to get more answers: https://bugzilla.mozilla.org/show_bug.cgi?id=1275400 Also lacking any positive answer there, he published all his fuzzing results here: https://github.com/brandonprry/ical-fuzz

At this point it's not clear whether those issues have been fixed in libical and if they have, it would be nice to know which commit fixed them. This is the point of this ticket.

A CVE number has been assigned to those issues: https://security-tracker.debian.org/tracker/CVE-2016-5824 (CVE assignment here: http://seclists.org/oss-sec/2016/q2/604)


Comments:
Comment by rhertzog on 2017-01-27 11:13:33+00:00:
Apparently #251 might be related.

---

Comment by winterz on 2017-01-27 15:59:47+00:00:
right. I had individual issues already assigned for those CVEs.   all of them are fixed now except for #253 which we don't know what to do about. 

Build script:
# Minimized build script with only core build commands
set -eu
cmake . -DBUILD_SHARED_LIBS=OFF -DICAL_GLIB=False
make install -j$(nproc)

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get install --yes cmake
RUN git clone https://github.com/libical/libical libical
RUN git -C libical checkout 43858141030ba123a4959231cadc9951b983f0fd
WORKDIR $SRC/libical
COPY build.sh $SRC/

Additional files:
filename: libical_fuzzer.cc
content: /*
# Copyright 2019 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.
#
################################################################################
*/

/*
  Usage:
    python infra/helper.py build_image libical
    python infra/helper.py build_fuzzers --sanitizer undefined|address|memory libical
    python infra/helper.py run_fuzzer libical libical_fuzzer
*/

#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include <libical/ical.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
    char *ical_string = (char*)malloc(size + 1);
    memcpy(ical_string, data, size);
    ical_string[size] = '\0';

    icalcomponent *component = icalparser_parse_string(ical_string);
    icalcomponent_free(component);

    free(ical_string);

    return 0;
}