Lucene search

K
hackeroneCatenacyberH1:827051
HistoryMar 23, 2020 - 10:54 a.m.

Open-Xchange: Use after free in smtp_server_connection_handle_command

2020-03-2310:54:20
catenacyber
hackerone.com
$500
13

0.009 Low

EPSS

Percentile

82.7%

Function smtp_server_connection_handle_command in src/lib-smtp/smtp-server-connection.c creates a variable named cmd with
cmd = smtp_server_command_new(tmp_conn, cmd_name, cmd_params);
It gets used with return (cmd == NULL || !cmd->input_locked); ie cmd->input_locked dereferences the pointer
But we can get to this code with cmd != NULL and cmd was freed

To do so, we can trigger in smtp_server_command_submit_reply the condition
if (conn != NULL && conn->bad_counter > conn->set.max_bad_commands) { which calls smtp_server_connection_terminate which ends up freeing cmd (smtp_server_connection_close, smtp_server_connection_disconnect, smtp_server_command_unref)
To do so, it is enough do send enough linefeeds characters like “\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n” to the server.

To me the flawed logic is to have the check if (!smtp_server_connection_unref(&tmp_conn)) {
This decreases reference count only once, which has been increased before at least twice in smtp_server_connection_handle_command and its caller smtp_server_connection_input

Proposed patch is

diff --git a/src/lib-smtp/smtp-server-connection.c b/src/lib-smtp/smtp-server-connection.c
index 404acc888b..ab8746fb2b 100644
--- a/src/lib-smtp/smtp-server-connection.c
+++ b/src/lib-smtp/smtp-server-connection.c
@@ -295,8 +295,10 @@ smtp_server_connection_handle_command(struct smtp_server_connection *conn,
        struct smtp_server_command *cmd;
 
        smtp_server_connection_ref(tmp_conn);
+       int refcount = tmp_conn->refcount;
        cmd = smtp_server_command_new(tmp_conn, cmd_name, cmd_params);
-       if (!smtp_server_connection_unref(&tmp_conn)) {
+       if (refcount > tmp_conn->refcount ||
+               !smtp_server_connection_unref(&tmp_conn)) {
                /* the command start callback managed to get this connection
                   destroyed */
                return FALSE;

This was found by fuzzing

Impact

The attacker can use this as a denial of service against the SMTP server.