7.5 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
HIGH
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
5 Medium
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
PARTIAL
AV:N/AC:L/Au:N/C:N/I:N/A:P
Sending a message to the local delivery agent with the number of MIME parts more than the dovecot core threshold of MIME parts results in i_panic. In the case of LMTP server it causes the child to abort connection. I believe that this can be quite problematic, if such a message lands in the queue of some MTA that will try sending the message again and again, effectively stopping the queue.
Here is the output from my fuzzer, that shows the call stack:
INFO: Seed: 4055316033
INFO: Loaded 1 modules (33862 inline 8-bit counters): 33862 [0x9c80f0, 0x9d0536),
INFO: Loaded 1 PC tables (33862 PCs): 33862 [0x9d0538,0xa54998),
./fuzz-message-libfuzzer: Running 1 inputs 1 time(s) each.
Running: crashes/minimized/afl_minimized/minimized
Panic: file message-parser.c: line 167 (message_part_append): assertion failed: (ctx->total_parts_count <= ctx->max_total_mime_parts)
Error: Raw backtrace: ./fuzz-message-libfuzzer() [0x48fb91] -> ./fuzz-message-libfuzzer() [0x63014a] -> ./fuzz-message-libfuzzer() [0x63074a] -> ./fuzz-message-libfuzzer() [0x5851ca] -> ./fuzz-message-libfuzzer() [0x57ee31] -> ./fuzz-message-libfuzzer() [0x57e4de] -> ./fuzz-message-libfuzzer() [0x57e671] -> ./fuzz-message-libfuzzer() [0x55ff89] -> ./fuzz-message-libfuzzer() [0x55b6dd] -> ./fuzz-message-libfuzzer() [0x550787] -> ./fuzz-message-libfuzzer() [0x542e10] -> ./fuzz-message-libfuzzer() [0x445087] -> ./fuzz-message-libfuzzer() [0x428c4b] -> ./fuzz-message-libfuzzer() [0x436554] -> ./fuzz-message-libfuzzer() [0x41f463] -> /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7) [0x7fc2357a9b97] -> ./fuzz-message-libfuzzer() [0x41f4ba]
==16440== ERROR: libFuzzer: deadly signal
#0 0x50e9c8 in __sanitizer_print_stack_trace /home/rumata/Tools/llvm-project/compiler-rt/lib/asan/asan_stack.cpp:86
#1 0x469ed2 in fuzzer::PrintStackTrace() /home/rumata/Tools/llvm-project/compiler-rt/lib/fuzzer/FuzzerUtil.cpp:210
#2 0x41f180 in fuzzer::Fuzzer::CrashCallback() (.part.279) /home/rumata/Tools/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:233
#3 0x444917 in fuzzer::Fuzzer::CrashCallback() /home/rumata/Tools/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:205
#4 0x444917 in fuzzer::Fuzzer::StaticCrashSignalCallback() /home/rumata/Tools/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:204
#5 0x7fc23654d89f (/lib/x86_64-linux-gnu/libpthread.so.0+0x1289f)
#6 0x7fc2357c6f46 in __libc_signal_restore_set /build/glibc-2ORdQG/glibc-2.27/signal/../sysdeps/unix/sysv/linux/nptl-signals.h:80
#7 0x7fc2357c6f46 in raise /build/glibc-2ORdQG/glibc-2.27/signal/../sysdeps/unix/sysv/linux/raise.c:48
#8 0x7fc2357c88b0 in abort /build/glibc-2ORdQG/glibc-2.27/stdlib/abort.c:79
#9 0x5852dd in default_fatal_finish /home/rumata/Documents/Collaboration/Fuzzing/pigeonhole/dovecot_fuzz/src/lib/failures.c:459:3
#10 0x57ee30 in fatal_handler_real /home/rumata/Documents/Collaboration/Fuzzing/pigeonhole/dovecot_fuzz/src/lib/failures.c:471:2
#11 0x57e4dd in default_fatal_handler /home/rumata/Documents/Collaboration/Fuzzing/pigeonhole/dovecot_fuzz/src/lib/failures.c:479:2
#12 0x57e670 in i_panic /home/rumata/Documents/Collaboration/Fuzzing/pigeonhole/dovecot_fuzz/src/lib/failures.c:523:2
#13 0x55ff88 in message_part_append /home/rumata/Documents/Collaboration/Fuzzing/pigeonhole/dovecot_fuzz/src/lib-mail/message-parser.c:167:2
#14 0x55b6dc in parse_next_body_message_rfc822_init /home/rumata/Documents/Collaboration/Fuzzing/pigeonhole/dovecot_fuzz/src/lib-mail/message-parser.c:225:2
#15 0x550786 in message_parser_parse_next_block /home/rumata/Documents/Collaboration/Fuzzing/pigeonhole/dovecot_fuzz/src/lib-mail/message-parser.c:816:16
#16 0x542e0f in LLVMFuzzerTestOneInput /home/rumata/Documents/Collaboration/Fuzzing/pigeonhole/dovecot_fuzz/src/lib-mail/message_fuzzer.c:28:16
#17 0x445086 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/rumata/Tools/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:559
#18 0x428c4a in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /home/rumata/Tools/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:301
#19 0x436553 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/rumata/Tools/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:801
#20 0x41f462 in main /home/rumata/Tools/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20
#21 0x7fc2357a9b96 in __libc_start_main /build/glibc-2ORdQG/glibc-2.27/csu/../csu/libc-start.c:310
#22 0x41f4b9 in _start (/home/rumata/Documents/Collaboration/Fuzzing/pigeonhole/fuzz/fuzz-message-libfuzzer+0x41f4b9)
Basically, the following assertion causes the panic.
i_assert(ctx->total_parts_count <= ctx->max_total_mime_parts);
I’m not sure, what is the best solution here. That assertion is probably there for a reason, but if there is no actual need for it, maybe it could be dropped. It it can’t, probably there should be a more graceful way, that actually returns an error instead of aborting the process alltogether.
The attacker could probably use it to block a queue from some MTA to dovecot LMTP server.
7.5 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
HIGH
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
5 Medium
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
NONE
Integrity Impact
NONE
Availability Impact
PARTIAL
AV:N/AC:L/Au:N/C:N/I:N/A:P