Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit09ec55b

Browse files
committed
Fix buffer overflow when parsing SCRAM verifiers in backend
Any authenticated user can overflow a stack-based buffer by changing theuser's own password to a purpose-crafted value. This often suffices toexecute arbitrary code as the PostgreSQL operating system account.This fix is contributed by multiple folks, based on an initial analysisfrom Tom Lane. This issue has been introduced by 68e61ee, so it waspossible to make use of it at authentication time. It became moreeasily to trigger after ccae190 which has made the SCRAM parsing morestrict when changing a password, in the case where the client passesdown a verifier already hashed using SCRAM. Back-patch to v10 whereSCRAM has been introduced.Reported-by: Alexander LakhinAuthor: Jonathan Katz, Heikki Linnakangas, Michael PaquierSecurity:CVE-2019-10164Backpatch-through: 10
1 parent3412030 commit09ec55b

File tree

3 files changed

+68
-8
lines changed

3 files changed

+68
-8
lines changed

‎src/backend/libpq/auth-scram.c

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,12 @@ scram_verify_plain_password(const char *username, const char *password,
542542
/*
543543
* Parse and validate format of given SCRAM verifier.
544544
*
545+
* On success, the iteration count, salt, stored key, and server key are
546+
* extracted from the verifier, and returned to the caller. For 'stored_key'
547+
* and 'server_key', the caller must pass pre-allocated buffers of size
548+
* SCRAM_KEY_LEN. Salt is returned as a base64-encoded, null-terminated
549+
* string. The buffer for the salt is palloc'd by this function.
550+
*
545551
* Returns true if the SCRAM verifier has been parsed, and false otherwise.
546552
*/
547553
bool
@@ -557,6 +563,8 @@ parse_scram_verifier(const char *verifier, int *iterations, char **salt,
557563
char*serverkey_str;
558564
intdecoded_len;
559565
char*decoded_salt_buf;
566+
char*decoded_stored_buf;
567+
char*decoded_server_buf;
560568

561569
/*
562570
* The verifier is of form:
@@ -589,36 +597,47 @@ parse_scram_verifier(const char *verifier, int *iterations, char **salt,
589597
* although we return the encoded version to the caller.
590598
*/
591599
decoded_salt_buf=palloc(pg_b64_dec_len(strlen(salt_str)));
592-
decoded_len=pg_b64_decode(salt_str,strlen(salt_str),decoded_salt_buf);
600+
decoded_len=pg_b64_decode(salt_str,strlen(salt_str),
601+
decoded_salt_buf);
593602
if (decoded_len<0)
594603
gotoinvalid_verifier;
595604
*salt=pstrdup(salt_str);
596605

597606
/*
598607
* Decode StoredKey and ServerKey.
599608
*/
600-
if (pg_b64_dec_len(strlen(storedkey_str)!=SCRAM_KEY_LEN))
601-
gotoinvalid_verifier;
609+
decoded_stored_buf=palloc(pg_b64_dec_len(strlen(storedkey_str)));
602610
decoded_len=pg_b64_decode(storedkey_str,strlen(storedkey_str),
603-
(char*)stored_key);
611+
decoded_stored_buf);
604612
if (decoded_len!=SCRAM_KEY_LEN)
605613
gotoinvalid_verifier;
614+
memcpy(stored_key,decoded_stored_buf,SCRAM_KEY_LEN);
606615

607-
if (pg_b64_dec_len(strlen(serverkey_str)!=SCRAM_KEY_LEN))
608-
gotoinvalid_verifier;
616+
decoded_server_buf=palloc(pg_b64_dec_len(strlen(serverkey_str)));
609617
decoded_len=pg_b64_decode(serverkey_str,strlen(serverkey_str),
610-
(char*)server_key);
618+
decoded_server_buf);
611619
if (decoded_len!=SCRAM_KEY_LEN)
612620
gotoinvalid_verifier;
621+
memcpy(server_key,decoded_server_buf,SCRAM_KEY_LEN);
613622

614623
return true;
615624

616625
invalid_verifier:
617-
pfree(v);
618626
*salt=NULL;
619627
return false;
620628
}
621629

630+
/*
631+
* Generate plausible SCRAM verifier parameters for mock authentication.
632+
*
633+
* In a normal authentication, these are extracted from the verifier
634+
* stored in the server. This function generates values that look
635+
* realistic, for when there is no stored verifier.
636+
*
637+
* Like in parse_scram_verifier(), for 'stored_key' and 'server_key', the
638+
* caller must pass pre-allocated buffers of size SCRAM_KEY_LEN, and
639+
* the buffer for the salt is palloc'd by this function.
640+
*/
622641
staticvoid
623642
mock_scram_verifier(constchar*username,int*iterations,char**salt,
624643
uint8*stored_key,uint8*server_key)

‎src/test/regress/expected/password.out

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,26 @@ SELECT rolpassword FROM pg_authid WHERE rolname='regress_passwd_empty';
100100

101101
(1 row)
102102

103+
-- Test with invalid stored and server keys.
104+
--
105+
-- The first is valid, to act as a control. The others have too long
106+
-- stored/server keys. They will be re-hashed.
107+
CREATE ROLE regress_passwd_sha_len0 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
108+
CREATE ROLE regress_passwd_sha_len1 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96RqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
109+
CREATE ROLE regress_passwd_sha_len2 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=';
110+
-- Check that the invalid verifiers were re-hashed. A re-hashed verifier
111+
-- should not contain the original salt.
112+
SELECT rolname, rolpassword not like '%A6xHKoH/494E941doaPOYg==%' as is_rolpassword_rehashed
113+
FROM pg_authid
114+
WHERE rolname LIKE 'regress_passwd_sha_len%'
115+
ORDER BY rolname;
116+
rolname | is_rolpassword_rehashed
117+
-------------------------+-------------------------
118+
regress_passwd_sha_len0 | f
119+
regress_passwd_sha_len1 | t
120+
regress_passwd_sha_len2 | t
121+
(3 rows)
122+
103123
DROP ROLE regress_passwd1;
104124
DROP ROLE regress_passwd2;
105125
DROP ROLE regress_passwd3;
@@ -109,6 +129,9 @@ DROP ROLE regress_passwd6;
109129
DROP ROLE regress_passwd7;
110130
DROP ROLE regress_passwd8;
111131
DROP ROLE regress_passwd_empty;
132+
DROP ROLE regress_passwd_sha_len0;
133+
DROP ROLE regress_passwd_sha_len1;
134+
DROP ROLE regress_passwd_sha_len2;
112135
-- all entries should have been removed
113136
SELECT rolname, rolpassword
114137
FROM pg_authid

‎src/test/regress/sql/password.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@ ALTER ROLE regress_passwd_empty PASSWORD 'md585939a5ce845f1a1b620742e3c659e0a';
7575
ALTER ROLE regress_passwd_empty PASSWORD'SCRAM-SHA-256$4096:hpFyHTUsSWcR7O9P$LgZFIt6Oqdo27ZFKbZ2nV+vtnYM995pDh9ca6WSi120=:qVV5NeluNfUPkwm7Vqat25RjSPLkGeoZBQs6wVv+um4=';
7676
SELECT rolpasswordFROM pg_authidWHERE rolname='regress_passwd_empty';
7777

78+
-- Test with invalid stored and server keys.
79+
--
80+
-- The first is valid, to act as a control. The others have too long
81+
-- stored/server keys. They will be re-hashed.
82+
CREATE ROLE regress_passwd_sha_len0 PASSWORD'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
83+
CREATE ROLE regress_passwd_sha_len1 PASSWORD'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96RqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
84+
CREATE ROLE regress_passwd_sha_len2 PASSWORD'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=';
85+
86+
-- Check that the invalid verifiers were re-hashed. A re-hashed verifier
87+
-- should not contain the original salt.
88+
SELECT rolname, rolpassword notlike'%A6xHKoH/494E941doaPOYg==%'as is_rolpassword_rehashed
89+
FROM pg_authid
90+
WHERE rolnameLIKE'regress_passwd_sha_len%'
91+
ORDER BY rolname;
92+
7893
DROP ROLE regress_passwd1;
7994
DROP ROLE regress_passwd2;
8095
DROP ROLE regress_passwd3;
@@ -84,6 +99,9 @@ DROP ROLE regress_passwd6;
8499
DROP ROLE regress_passwd7;
85100
DROP ROLE regress_passwd8;
86101
DROP ROLE regress_passwd_empty;
102+
DROP ROLE regress_passwd_sha_len0;
103+
DROP ROLE regress_passwd_sha_len1;
104+
DROP ROLE regress_passwd_sha_len2;
87105

88106
-- all entries should have been removed
89107
SELECT rolname, rolpassword

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp