Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Net::MailMessage: Double free if Content-Disposition header is empty #4687

Closed
tyler92 opened this issue Sep 12, 2024 · 1 comment · Fixed by #4688
Closed

Net::MailMessage: Double free if Content-Disposition header is empty #4687

tyler92 opened this issue Sep 12, 2024 · 1 comment · Fixed by #4688

Comments

@tyler92
Copy link
Contributor

tyler92 commented Sep 12, 2024

Describe the bug

During the fuzzing test for Poco::Net::MailMessage ASAN reports a heap-use-after-free (which is actually double-free) issue. This happens if a parsed message is a multipart message with an empty Content-Disposition header.

To Reproduce

Poco::MemoryInputStream stream(input.data(), input.size());
Poco::Net::MailMessage mail;
mail.read(stream);

with the following input: crash-a50113a66f7c8d5530f3446b7c74a5cbc04668a2.txt

Expected behavior

The message is parsed without an error.

Logs

=================================================================
==575941==ERROR: AddressSanitizer: heap-use-after-free on address 0x515000615380 at pc 0x7fd7e5e2e9f9 bp 0x7ffc405f5e50 sp 0x7ffc405f5e48
READ of size 8 at 0x515000615380 thread T0
    #0 0x7fd7e5e2e9f8 in Poco::Net::MailMessage::~MailMessage() poco/Net/src/MailMessage.cpp:219:3
    #1 0x561b1a8ed8e3 in LLVMFuzzerTestOneInput poco/fuzzing/http_messages_fuzzer.cc:47:3
    #2 0x561b1a7f9920 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4c920)
    #3 0x561b1a7f9095 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4c095)
    #4 0x561b1a7fa875 in fuzzer::Fuzzer::MutateAndTestOne() (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4d875)
    #5 0x561b1a7fb485 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4e485)
    #6 0x561b1a7e95eb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x3c5eb)
    #7 0x561b1a812622 in main (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x65622)
    #8 0x7fd7e4b82d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #9 0x7fd7e4b82e3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #10 0x561b1a7dea54 in _start (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x31a54)

0x515000615380 is located 0 bytes inside of 504-byte region [0x515000615380,0x515000615578)
freed by thread T0 here:
    #0 0x561b1a8ebbbd in operator delete(void*) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x13ebbd)
    #1 0x7fd7e5fe99b3 in Poco::Net::StringPartSource::~StringPartSource() poco/Net/src/StringPartSource.cpp:45:1
    #2 0x7fd7e5e2ea3b in Poco::Net::MailMessage::~MailMessage() poco/Net/src/MailMessage.cpp:219:3
    #3 0x561b1a8ed8e3 in LLVMFuzzerTestOneInput poco/fuzzing/http_messages_fuzzer.cc:47:3
    #4 0x561b1a7f9920 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4c920)
    #5 0x561b1a7f9095 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4c095)
    #6 0x561b1a7fa875 in fuzzer::Fuzzer::MutateAndTestOne() (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4d875)
    #7 0x561b1a7fb485 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4e485)
    #8 0x561b1a7e95eb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x3c5eb)
    #9 0x561b1a812622 in main (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x65622)
    #10 0x7fd7e4b82d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

previously allocated by thread T0 here:
    #0 0x561b1a8eb35d in operator new(unsigned long) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x13e35d)
    #1 0x7fd7e5e39176 in Poco::Net::MailMessage::createPartStore(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) poco/Net/src/MailMessage.cpp:694:30
    #2 0x7fd7e5e3c197 in Poco::Net::(anonymous namespace)::MultiPartHandler::handlePart(Poco::Net::MessageHeader const&, std::istream&) poco/Net/src/MailMessage.cpp:102:30
    #3 0x7fd7e5e3731d in Poco::Net::MailMessage::handlePart(std::istream&, Poco::Net::MessageHeader const&, Poco::Net::PartHandler&) poco/Net/src/MailMessage.cpp:537:10
    #4 0x7fd7e5e332a8 in Poco::Net::MailMessage::readPart(std::istream&, Poco::Net::MessageHeader const&, Poco::Net::PartHandler&) poco/Net/src/MailMessage.cpp:514:9
    #5 0x7fd7e5e32916 in Poco::Net::MailMessage::readMultipart(std::istream&, Poco::Net::PartHandler&) poco/Net/src/MailMessage.cpp:495:3
    #6 0x7fd7e5e33be2 in Poco::Net::MailMessage::read(std::istream&) poco/Net/src/MailMessage.cpp:363:3
    #7 0x561b1a8ed8b5 in LLVMFuzzerTestOneInput poco/fuzzing/http_messages_fuzzer.cc:46:10
    #8 0x561b1a7f9920 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4c920)
    #9 0x561b1a7f9095 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4c095)
    #10 0x561b1a7fa875 in fuzzer::Fuzzer::MutateAndTestOne() (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4d875)
    #11 0x561b1a7fb485 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x4e485)
    #12 0x561b1a7e95eb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x3c5eb)
    #13 0x561b1a812622 in main (poco/fuzzing/prefix/bin/http_messages_fuzzer+0x65622)
    #14 0x7fd7e4b82d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

SUMMARY: AddressSanitizer: heap-use-after-free poco/Net/src/MailMessage.cpp:219:3 in Poco::Net::MailMessage::~MailMessage()
Shadow bytes around the buggy address:
  0x515000615100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x515000615180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x515000615200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x515000615280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x515000615300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x515000615380:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x515000615400: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x515000615480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x515000615500: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
  0x515000615580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x515000615600: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
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
==575941==ABORTING
MS: 1 CrossOver-; base unit: 1cb911899a10687a9b6b2eb3ef9db81abcc6c10c
artifact_prefix='./'; Test unit written to ./crash-a50113a66f7c8d5530f3446b7c74a5cbc04668a2
@tyler92
Copy link
Contributor Author

tyler92 commented Sep 13, 2024

@matejk I believe it makes sense to add 'security' label here to have a clear changelog

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants