Commit b6742117 authored by Michael Paquier's avatar Michael Paquier

Fix buffer overflow when processing SCRAM final message in libpq

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
parent 09ec55b9
...@@ -580,6 +580,12 @@ read_server_first_message(fe_scram_state *state, char *input) ...@@ -580,6 +580,12 @@ read_server_first_message(fe_scram_state *state, char *input)
state->saltlen = pg_b64_decode(encoded_salt, state->saltlen = pg_b64_decode(encoded_salt,
strlen(encoded_salt), strlen(encoded_salt),
state->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); iterations_str = read_attr_value(&input, 'i', &conn->errorMessage);
if (iterations_str == NULL) if (iterations_str == NULL)
...@@ -610,6 +616,7 @@ read_server_final_message(fe_scram_state *state, char *input) ...@@ -610,6 +616,7 @@ read_server_final_message(fe_scram_state *state, char *input)
{ {
PGconn *conn = state->conn; PGconn *conn = state->conn;
char *encoded_server_signature; char *encoded_server_signature;
char *decoded_server_signature;
int server_signature_len; int server_signature_len;
state->server_final_message = strdup(input); state->server_final_message = strdup(input);
...@@ -645,15 +652,27 @@ read_server_final_message(fe_scram_state *state, char *input) ...@@ -645,15 +652,27 @@ read_server_final_message(fe_scram_state *state, char *input)
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (garbage at end of server-final-message)\n")); 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, server_signature_len = pg_b64_decode(encoded_server_signature,
strlen(encoded_server_signature), strlen(encoded_server_signature),
state->ServerSignature); decoded_server_signature);
if (server_signature_len != SCRAM_KEY_LEN) if (server_signature_len != SCRAM_KEY_LEN)
{ {
free(decoded_server_signature);
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (invalid server signature)\n")); libpq_gettext("malformed SCRAM message (invalid server signature)\n"));
return false; return false;
} }
memcpy(state->ServerSignature, decoded_server_signature, SCRAM_KEY_LEN);
free(decoded_server_signature);
return true; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment