[libsoup] add limit on maximum header size to avoid DOS (bug #792173)



commit f33de90ae9af9e340198ed2eead1f9cfb1793fd2
Author: Michele Dionisio <michele dionisio gmail com>
Date:   Sat Jan 6 12:03:48 2018 +0100

    add limit on maximum header size to avoid DOS (bug #792173)
    
    Signed-off-by: Michele Dionisio <michele dionisio gmail com>

 libsoup/soup-message-io.c |    9 +++++++++
 tests/misc-test.c         |   33 +++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 0 deletions(-)
---
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index fb505fa..3a7d735 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -94,6 +94,7 @@ typedef struct {
 static void io_run (SoupMessage *msg, gboolean blocking);
 
 #define RESPONSE_BLOCK_SIZE 8192
+#define HEADER_SIZE_LIMIT (64 * 1024)
 
 void
 soup_message_io_cleanup (SoupMessage *msg)
@@ -254,6 +255,14 @@ read_headers (SoupMessage *msg, gboolean blocking,
                                break;
                        }
                }
+
+               if (io->read_header_buf->len > HEADER_SIZE_LIMIT) {
+                       soup_message_set_status (msg, SOUP_STATUS_MALFORMED);
+                       g_set_error_literal (error, G_IO_ERROR,
+                                            G_IO_ERROR_PARTIAL_INPUT,
+                                            _("Header too big"));
+                       return FALSE;
+               }
        }
 
        io->read_header_buf->data[io->read_header_buf->len] = '\0';
diff --git a/tests/misc-test.c b/tests/misc-test.c
index 6d43bd7..8cbda80 100644
--- a/tests/misc-test.c
+++ b/tests/misc-test.c
@@ -120,6 +120,38 @@ do_host_test (void)
        g_object_unref (two);
 }
 
+/* request with too big header should be discarded with a IO error to 
+ * prevent DOS attacks.
+ */
+static void
+do_host_big_header (void)
+{
+       SoupMessage *msg;
+       SoupSession *session;
+       int i;
+
+       g_test_bug ("792173");
+
+       session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+
+       msg = soup_message_new_from_uri ("GET", base_uri);
+       for (i = 0; i < 2048; i++) {
+               char *key = g_strdup_printf ("test-long-header-key%d", i);
+               char *value = g_strdup_printf ("test-long-header-key%d", i);
+               soup_message_headers_append (msg->request_headers, key, value);
+               g_free (value);
+               g_free (key);
+       }
+
+       soup_session_send_message (session, msg);
+
+       soup_test_session_abort_unref (session);
+
+       soup_test_assert_message_status (msg, SOUP_STATUS_IO_ERROR);
+
+       g_object_unref (msg);
+}
+
 /* Dropping the application's ref on the session from a callback
  * should not cause the session to be freed at an incorrect time.
  * (This test will crash if it fails.)
@@ -1182,6 +1214,7 @@ main (int argc, char **argv)
                ssl_base_uri = soup_test_server_get_uri (ssl_server, "https", "127.0.0.1");
        }
 
+       g_test_add_func ("/misc/bigheader", do_host_big_header);
        g_test_add_func ("/misc/host", do_host_test);
        g_test_add_func ("/misc/callback-unref/msg", do_callback_unref_test);
        g_test_add_func ("/misc/callback-unref/req", do_callback_unref_req_test);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]