From 3311d3490146d586a27a245776c6b515df136b02 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 21 Jun 2018 14:38:37 +0100 Subject: [Feature] Address ZeroFont exploit --- rules/html.lua | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 4 deletions(-) (limited to 'rules') diff --git a/rules/html.lua b/rules/html.lua index 56cf22f11..7a0f5127b 100644 --- a/rules/html.lua +++ b/rules/html.lua @@ -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 = { -- cgit v1.2.3