]> granicus.if.org Git - postgresql/commitdiff
Fix buffer overflow when processing SCRAM final message in libpq
authorMichael Paquier <michael@paquier.xyz>
Mon, 17 Jun 2019 13:13:57 +0000 (22:13 +0900)
committerMichael Paquier <michael@paquier.xyz>
Mon, 17 Jun 2019 13:13:57 +0000 (22:13 +0900)
When a client connects to a rogue server sending specifically-crafted
messages, this can suffice to execute arbitrary code as the operating
system account used by the client.

While on it, fix one error handling when decoding an incorrect salt
included in the first message received from server.

Author: Michael Paquier
Reviewed-by: Jonathan Katz, Heikki Linnakangas
Security: CVE-2019-10164
Backpatch-through: 10

src/interfaces/libpq/fe-auth-scram.c

index 719570a45ce2ac7deccf53e1437132084877e3c6..babdc06198479db92b28d2bc3483cace11840b56 100644 (file)
@@ -580,6 +580,12 @@ read_server_first_message(fe_scram_state *state, char *input)
        state->saltlen = pg_b64_decode(encoded_salt,
                                                                   strlen(encoded_salt),
                                                                   state->salt);
+       if (state->saltlen < 0)
+       {
+               printfPQExpBuffer(&conn->errorMessage,
+                                                 libpq_gettext("malformed SCRAM message (invalid salt)\n"));
+               return false;
+       }
 
        iterations_str = read_attr_value(&input, 'i', &conn->errorMessage);
        if (iterations_str == NULL)
@@ -610,6 +616,7 @@ read_server_final_message(fe_scram_state *state, char *input)
 {
        PGconn     *conn = state->conn;
        char       *encoded_server_signature;
+       char       *decoded_server_signature;
        int                     server_signature_len;
 
        state->server_final_message = strdup(input);
@@ -645,15 +652,27 @@ read_server_final_message(fe_scram_state *state, char *input)
                printfPQExpBuffer(&conn->errorMessage,
                                                  libpq_gettext("malformed SCRAM message (garbage at end of server-final-message)\n"));
 
+       server_signature_len = pg_b64_dec_len(strlen(encoded_server_signature));
+       decoded_server_signature = malloc(server_signature_len);
+       if (!decoded_server_signature)
+       {
+               printfPQExpBuffer(&conn->errorMessage,
+                                                 libpq_gettext("out of memory\n"));
+               return false;
+       }
+
        server_signature_len = pg_b64_decode(encoded_server_signature,
                                                                                 strlen(encoded_server_signature),
-                                                                                state->ServerSignature);
+                                                                                decoded_server_signature);
        if (server_signature_len != SCRAM_KEY_LEN)
        {
+               free(decoded_server_signature);
                printfPQExpBuffer(&conn->errorMessage,
                                                  libpq_gettext("malformed SCRAM message (invalid server signature)\n"));
                return false;
        }
+       memcpy(state->ServerSignature, decoded_server_signature, SCRAM_KEY_LEN);
+       free(decoded_server_signature);
 
        return true;
 }