[exim-cvs] SECURITY: Avoid decrement of dkim_collect_input i…

Inizio della pagina
Delete this message
Reply to this message
Autore: Exim Git Commits Mailing List
Data:  
To: exim-cvs
Oggetto: [exim-cvs] SECURITY: Avoid decrement of dkim_collect_input if already at 0
Gitweb: https://git.exim.org/exim.git/commitdiff/d97d073f5dc62d2a7352c5cf6506a771876d7f11
Commit:     d97d073f5dc62d2a7352c5cf6506a771876d7f11
Parent:     87804cc1f325a3eb5a562b708deb0293402e1f8f
Author:     Heiko Schlittermann (HS12-RIPE) <hs@???>
AuthorDate: Wed Nov 25 22:58:58 2020 +0100
Committer:  Heiko Schlittermann (HS12-RIPE) <hs@???>
CommitDate: Thu May 27 21:30:37 2021 +0200


    SECURITY: Avoid decrement of dkim_collect_input if already at 0


    Credits: Qualys


        5/ receive_msg() calls dkim_exim_verify_finish(), which sets
        dkim_collect_input to 0 and calls pdkim_feed_finish(), which calls
        pdkim_header_complete(), which decreases dkim_collect_input to UINT_MAX,
        which reactivates the DKIM code.


        As a result, pdkim_feed() is called again (through receive_getc at the
        end of receive_msg()), but functions like pdkim_finish_bodyhash() and
        exim_sha_finish() have already been called (in pdkim_feed_finish()).
        This suggests a use-after-free.


        But it seems that a use-after-free would happen only with
        EVP_DigestFinal() (in exim_sha_finish()), which does not seem to be
        reachable via DKIM (no SHA3). But we checked OpenSSL only, not GnuTLS.


        Here is a proof of concept that triggers the bug (which came very close
        to a security vulnerability):


        (sleep 10; echo 'EHLO test'; sleep 3; echo 'MAIL FROM:<>'; sleep 3; echo 'RCPT TO:postmaster'; sleep 3; echo 'BDAT 42 LAST'; date >&2; sleep 30; printf 'not a valid header line\r\nDKIM-Signature:\r\nXXX'; sleep 30) | nc -n -v 192.168.56.102 25


        (gdb) print &dkim_collect_input
        $2 = (unsigned int *) 0x55e180386d90 <dkim_collect_input>
        (gdb) watch *(unsigned int *) 0x55e180386d90


        Hardware watchpoint 1: *(unsigned int *) 0x55e180386d90
        Old value = 0
        New value = 4294967295
        #0  0x000055e18031f805 in pdkim_header_complete (ctx=ctx@entry=0x55e181b9e8e0) at pdkim.c:1006
        #1  0x000055e18032106c in pdkim_feed_finish (ctx=0x55e181b9e8e0, return_signatures=0x55e180386d78 <dkim_signatures>, err=err@entry=0x7ffe443e1d00) at pdkim.c:1490
        #2  0x000055e1802a3280 in dkim_exim_verify_finish () at dkim.c:328
        #3  0x000055e1802c9d1d in receive_msg (extract_recip=extract_recip@entry=0) at receive.c:3409


    (cherry picked from commit e3674091056ac05eb7ef1c504accce790c434bd7)
    (cherry picked from commit 8b39dd074e3ec70cbda70a52cef5b71ecbf69499)
---
 src/src/pdkim/pdkim.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c
index ca16e2b..b4301b5 100644
--- a/src/src/pdkim/pdkim.c
+++ b/src/src/pdkim/pdkim.c
@@ -1003,7 +1003,7 @@ else
       last_sig->next = sig;
       }


-    if (--dkim_collect_input == 0)
+    if (dkim_collect_input && --dkim_collect_input == 0)
       {
       ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
       ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0';