]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Address ZeroFont exploit
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 21 Jun 2018 13:38:37 +0000 (14:38 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 21 Jun 2018 13:38:37 +0000 (14:38 +0100)
rules/html.lua

index 56cf22f114f4177abab64d601128c006d51ce8df..7a0f5127b45039b68cecfdef261309388fae54d7 100644 (file)
@@ -168,12 +168,16 @@ rspamd_config.R_SUSPICIOUS_IMAGES = {
   description = 'Message contains many suspicious messages'
 }
 
-rspamd_config.R_WHITE_ON_WHITE = {
+local vis_check_id = rspamd_config:register_symbol{
+  name = 'HTML_VISIBLE_CHECKS',
+  type = 'callback',
   callback = function(task)
     local tp = task:get_text_parts() -- get text parts in a message
     local ret = false
     local diff = 0.0
     local transp_rate = 0
+    local invisible_blocks = 0
+    local zero_size_blocks = 0
     local arg
 
     for _,p in ipairs(tp) do -- iterate over text parts array using `ipairs`
@@ -185,6 +189,14 @@ rspamd_config.R_WHITE_ON_WHITE = {
         hc:foreach_tag({'font', 'span', 'div', 'p'}, function(tag)
           local bl = tag:get_extra()
           if bl then
+            if not bl['visible'] then
+              invisible_blocks = invisible_blocks + 1
+            end
+
+            if bl['font_size'] and bl['font_size'] == 0 then
+              zero_size_blocks = zero_size_blocks + 1
+            end
+
             if bl['bgcolor'] and bl['color'] and bl['visible'] then
 
               local color = bl['color']
@@ -197,6 +209,7 @@ rspamd_config.R_WHITE_ON_WHITE = {
 
               if diff < 0.1 then
                 ret = true
+                invisible_blocks = invisible_blocks + 1 -- This block is invisible
                 transp_len = (tag:get_content_length()) *
                   (0.1 - diff) * 5.0
                 normal_len = normal_len - tag:get_content_length()
@@ -223,17 +236,85 @@ rspamd_config.R_WHITE_ON_WHITE = {
         if transp_rate > 0.5 or transp_rate ~= transp_rate then
           transp_rate = 0.5
         end
-        return true,(transp_rate * 2.0),arg
+
+        task:insert_result('R_WHITE_ON_WHITE', (transp_rate * 2.0), arg)
       end
     end
 
-    return false
+    if invisible_blocks > 0 then
+      if invisible_blocks > 10 then
+        invisible_blocks = 10
+      end
+      local rates = { -- From 1 to 10
+        0.05,
+        0.1,
+        0.2,
+        0.3,
+        0.4,
+        0.5,
+        0.6,
+        0.7,
+        0.8,
+        1.0,
+      }
+      task:insert_result('MANY_INVISIBLE_PARTS', rates[invisible_blocks],
+          tostring(invisible_blocks))
+    end
+
+    if zero_size_blocks > 0 then
+      if zero_size_blocks > 5 then
+        if zero_size_blocks > 10 then
+          -- Full score
+          task:insert_result('ZERO_FONT', 1.0,
+              tostring(zero_size_blocks))
+        else
+          zero_size_blocks = 5
+        end
+      end
+
+      if zero_size_blocks <= 5 then
+        local rates = { -- From 1 to 5
+          0.1,
+          0.2,
+          0.2,
+          0.3,
+          0.5,
+        }
+        task:insert_result('ZERO_FONT', rates[zero_size_blocks],
+            tostring(zero_size_blocks))
+      end
+    end
   end,
+}
 
+rspamd_config:register_symbol{
+  type = 'virtual',
+  parent = vis_check_id,
+  name = 'R_WHITE_ON_WHITE',
+  description = 'Message contains low contrast text',
   score = 4.0,
   group = 'html',
   one_shot = true,
-  description = 'Message contains low contrast text'
+}
+
+rspamd_config:register_symbol{
+  type = 'virtual',
+  parent = vis_check_id,
+  name = 'ZERO_FONT',
+  description = 'Zero sized font used',
+  score = 10.0, -- Reached if more than 5 elements have zero size
+  one_shot = true,
+  group = 'html'
+}
+
+rspamd_config:register_symbol{
+  type = 'virtual',
+  parent = vis_check_id,
+  name = 'MANY_INVISIBLE_PARTS',
+  description = 'Many parts are visually hidden',
+  score = 6.0, -- Reached if more than 10 elements are hidden
+  one_shot = true,
+  group = 'html'
 }
 
 rspamd_config.EXT_CSS = {