]> source.dussan.org Git - rspamd.git/commitdiff
[Minor] Add some tags limit to avoid HTML parser DoS
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 13 Dec 2017 20:35:48 +0000 (20:35 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 13 Dec 2017 20:35:48 +0000 (20:35 +0000)
src/libserver/html.c
src/libserver/html.h

index fc08baeb5a9e36a7676a8d6792d9ddd73683ec94..26318db43fbb55f3866200454537b98e672ee89c 100644 (file)
@@ -28,6 +28,7 @@
 
 static sig_atomic_t tags_sorted = 0;
 static sig_atomic_t entities_sorted = 0;
+static const guint max_tags = 8192; /* Ignore tags if this maximum is reached */
 
 struct html_tag_def {
        const gchar *name;
@@ -997,8 +998,13 @@ rspamd_html_process_tag (rspamd_mempool_t *pool, struct html_content *hc,
                                nnode);
        }
 
+       if (hc->total_tags > max_tags) {
+               hc->flags |= RSPAMD_HTML_FLAG_TOO_MANY_TAGS;
+       }
+
        if (tag->id == -1) {
                /* Ignore unknown tags */
+               hc->total_tags ++;
                return FALSE;
        }
 
@@ -1006,25 +1012,26 @@ rspamd_html_process_tag (rspamd_mempool_t *pool, struct html_content *hc,
 
        if (!(tag->flags & CM_INLINE)) {
                /* Block tag */
-               nnode = g_node_new (tag);
-
                if (tag->flags & (FL_CLOSING|FL_CLOSED)) {
                        if (!*cur_level) {
                                msg_debug_html ("bad parent node");
-                               g_node_destroy (nnode);
                                return FALSE;
                        }
 
-                       g_node_append (*cur_level, nnode);
+                       if (hc->total_tags < max_tags) {
+                               nnode = g_node_new (tag);
+                               g_node_append (*cur_level, nnode);
 
-                       if (!rspamd_html_check_balance (nnode, cur_level)) {
-                               msg_debug_html (
-                                               "mark part as unbalanced as it has not pairable closing tags");
-                               hc->flags |= RSPAMD_HTML_FLAG_UNBALANCED;
-                               *balanced = FALSE;
-                       }
-                       else {
-                               *balanced = TRUE;
+                               if (!rspamd_html_check_balance (nnode, cur_level)) {
+                                       msg_debug_html (
+                                                       "mark part as unbalanced as it has not pairable closing tags");
+                                       hc->flags |= RSPAMD_HTML_FLAG_UNBALANCED;
+                                       *balanced = FALSE;
+                               } else {
+                                       *balanced = TRUE;
+                               }
+
+                               hc->total_tags ++;
                        }
                }
                else {
@@ -1043,8 +1050,13 @@ rspamd_html_process_tag (rspamd_mempool_t *pool, struct html_content *hc,
                                                hc->flags |= RSPAMD_HTML_FLAG_UNBALANCED;
                                                *balanced = FALSE;
                                                tag->parent = parent->parent;
-                                               g_node_append (parent->parent, nnode);
-                                               *cur_level = nnode;
+
+                                               if (hc->total_tags < max_tags) {
+                                                       nnode = g_node_new (tag);
+                                                       g_node_append (parent->parent, nnode);
+                                                       *cur_level = nnode;
+                                                       hc->total_tags ++;
+                                               }
 
                                                return TRUE;
                                        }
@@ -1053,10 +1065,15 @@ rspamd_html_process_tag (rspamd_mempool_t *pool, struct html_content *hc,
                                parent->content_length += tag->content_length;
                        }
 
-                       g_node_append (*cur_level, nnode);
+                       if (hc->total_tags < max_tags) {
+                               nnode = g_node_new (tag);
+                               g_node_append (*cur_level, nnode);
+
+                               if ((tag->flags & FL_CLOSED) == 0) {
+                                       *cur_level = nnode;
+                               }
 
-                       if ((tag->flags & FL_CLOSED) == 0) {
-                               *cur_level = nnode;
+                               hc->total_tags ++;
                        }
 
                        if (tag->flags & (CM_HEAD|CM_UNKNOWN|FL_IGNORE)) {
index 5216ad767d07ae6fe6bbb2f9b8d631ba4e72da06..84d5e2bc2e2c51828c33cfeb60648a7fe8c05064 100644 (file)
@@ -17,6 +17,7 @@
 #define RSPAMD_HTML_FLAG_UNBALANCED (1 << 3)
 #define RSPAMD_HTML_FLAG_UNKNOWN_ELEMENTS (1 << 4)
 #define RSPAMD_HTML_FLAG_DUPLICATE_ELEMENTS (1 << 5)
+#define RSPAMD_HTML_FLAG_TOO_MANY_TAGS (1 << 6)
 
 /*
  * Image flags
@@ -107,6 +108,7 @@ struct rspamd_task;
 struct html_content {
        GNode *html_tags;
        gint flags;
+       guint total_tags;
        struct html_color bgcolor;
        guchar *tags_seen;
        GPtrArray *images;