From 6a7edbf6608d10ef0c707c426511e667849518d7 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 5 May 2020 21:15:34 +0100 Subject: [PATCH 1/2] Fix SPA authenticator, checking client-supplied data before using it. Bug 2571 (cherry picked from commit 57aa14b216432be381b6295c312065b2fd034f86) --- doc/ChangeLog | 5 +++++ src/auths/spa.c | 22 ++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -62,6 +62,11 @@ JH/28 Fix the timeout on smtp response t [from GIT master] +JH/41 Bug 2571: Fix SPA authenticator. Running as a server, an offset supplied + by the client was not checked as pointing within response data before + being used. A malicious client could thus cause an out-of-bounds read and + possibly gain authentication. Fix by adding the check. + Exim version 4.92 ----------------- --- a/src/auths/spa.c +++ b/src/auths/spa.c @@ -139,7 +139,7 @@ SPAAuthChallenge challenge; SPAAuthResponse response; SPAAuthResponse *responseptr = &response; uschar msgbuf[2048]; -uschar *clearpass; +uschar *clearpass, *s; /* send a 334, MS Exchange style, and grab the client's request, unless we already have it via an initial response. */ @@ -197,6 +197,13 @@ that causes failure if the size of msgbu char *p = ((char*)responseptr) + IVAL(&responseptr->uUser.offset,0); int len = SVAL(&responseptr->uUser.len,0)/2; + if (p + len*2 >= CS (responseptr+1)) + { + DEBUG(D_auth) + debug_printf("auth_spa_server(): bad uUser spec in response\n"); + return FAIL; + } + if (len + 1 >= sizeof(msgbuf)) return FAIL; for (i = 0; i < len; ++i) { @@ -245,14 +252,17 @@ spa_smb_nt_encrypt (clearpass, challenge /* compare NT hash (LM may not be available) */ -if (memcmp(ntRespData, - ((unsigned char*)responseptr)+IVAL(&responseptr->ntResponse.offset,0), - 24) == 0) - /* success. we have a winner. */ +s = (US responseptr) + IVAL(&responseptr->ntResponse.offset,0); +if (s + 24 >= US (responseptr+1)) { - return auth_check_serv_cond(ablock); + DEBUG(D_auth) + debug_printf("auth_spa_server(): bad ntRespData spec in response\n"); + return FAIL; } +if (memcmp(ntRespData, s, 24) == 0) + return auth_check_serv_cond(ablock); /* success. we have a winner. */ + /* Expand server_condition as an authorization check (PH) */ return FAIL;