[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#9140) Side channel vulnerability at password check



Full_Name: Shou Chaofan
Version: 
OS: 
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (98.185.228.137)


Here is the implementation of lutil_memcmp at /libraries/liblutil/memcmp.c
int
(lutil_memcmp)(const void *v1, const void *v2, size_t n) 
{
    if (n != 0) {
		const unsigned char *s1=v1, *s2=v2;
        do {
            if (*s1++ != *s2++) return *--s1 - *--s2; // immediate return after
difference
        } while (--n != 0);
    }
    return 0;
} 
Later, it is redefined as memcpy.
Then this function is used in the password checking function to compare user
password and inputed password. This would lead to a timing attack / side channel
attack. 

Here are all usages related to comparison of plaintext password
/libraries/liblutil/passwd.c: 341
if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
		return ( passwd->bv_len == cred->bv_len ) ?
			memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
			: 1;
	}

Here are all usages related to comparison of hashed password (although this is
less exploitable, by bruteforcing based on hash value, with enough time,
attacker could still recover the password):
/contrib/slapd-modules/passwd/sha2/slapd-sha2.c:262
rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));

/contrib/slapd-modules/passwd/sha2/slapd-sha2.c:303
rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));

/contrib/slapd-modules/passwd/sha2/slapd-sha2.c:350
rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));

/contrib/slapd-modules/passwd/sha2/slapd-sha2.c:391
rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));

/contrib/slapd-modules/passwd/sha2/slapd-sha2.c:438
rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));

/contrib/slapd-modules/passwd/sha2/slapd-sha2.c:479
rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));

/libraries/liblutil/passwd.c: 526
rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));

/libraries/liblutil/passwd.c: 567
rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));

/libraries/liblutil/passwd.c: 613
rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));

/libraries/liblutil/passwd.c: 654
rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));

/libraries/liblutil/passwd.c: 894
return memcmp( PasswordHash, storedPasswordHash, 32) ? LUTIL_PASSWD_ERR :
LUTIL_PASSWD_OK;

etc..

A safer implementation is:
int
(lutil_safe_memcmp)(const void *v1, const void *v2, size_t n) 
{
    int c=0;
    if (n != 0) {
		const unsigned char *s1=v1, *s2=v2;
        do {
            if (*s1++ != *s2++ && c == 0) c += *--s1 - *--s2;
        } while (--n != 0);
    }
    return c;
}