From e0f0176eec5a4ce25ac56a45f48eb203a36ddf86 Mon Sep 17 00:00:00 2001 From: Steve Freegard Date: Thu, 27 Jul 2017 13:22:36 +0100 Subject: [PATCH] Improve CTYPE_MIXED_BOGUS and MIME_BASE64_TEXT rules --- rules/headers_checks.lua | 60 ++++++++++++++++++++++++++++++++++++---- rules/regexp/headers.lua | 11 -------- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/rules/headers_checks.lua b/rules/headers_checks.lua index 7932afc90..2e4bae307 100644 --- a/rules/headers_checks.lua +++ b/rules/headers_checks.lua @@ -916,14 +916,64 @@ rspamd_config.CTYPE_MIXED_BOGUS = { if (not ct) then return false end local parts = task:get_parts() if (not parts) then return false end - if (ct:lower():match('^multipart/mixed') ~= nil and #parts < 3) - then - return true, tostring(#parts) + if (not ct:lower():match('^multipart/mixed')) then return false end + local found = false + -- Check each part and look for a part that isn't multipart/* or text/plain or text/html + for _,p in ipairs(parts) do + local ct = p:get_header('Content-Type') + if (ct) then + ct = ct:lower() + if (ct:match('^multipart/') or + ct:match('^text/plain') or + ct:match('^text/html')) + then + -- Nothing + else + found = true + end + end + end + if (not found) then return true end + return false + end, + description = 'multipart/mixed without non-textual part', + score = 1.0, + group = 'headers' +} + +local function check_for_base64_text(part) + local ct = part:get_header('Content-Type') + if (not ct) then return false end + ct = ct:lower() + if (ct:match('^text')) then + -- Check encoding + local cte = part:get_header('Content-Transfer-Encoding') + if (cte and cte:lower():match('^base64')) then + return true + end + end + return false +end + +rspamd_config.MIME_BASE64_TEXT = { + callback = function(task) + -- Check outer part + if (check_for_base64_text(task)) then + return true + else + local parts = task:get_parts() + if (not parts) then return false end + -- Check each part and look for base64 encoded text parts + for _, part in ipairs(parts) do + if (check_for_base64_text(part)) then + return true + end + end end return false end, - description = 'multipart/mixed with less than 3 total parts', - score = 0.1, + description = 'Has text part encoded in base64', + score = 1.0, group = 'headers' } diff --git a/rules/regexp/headers.lua b/rules/regexp/headers.lua index a2e7f3829..4d9d2c77d 100644 --- a/rules/regexp/headers.lua +++ b/rules/regexp/headers.lua @@ -901,14 +901,3 @@ reconf['HAS_XOIP'] = { score = 0.0, group = 'headers' } - -reconf['MIME_BASE64_TEXT'] = { - re = string.format('(%s && %s) || (%s && %s)', - 'Content-Type=/^text/Hi', - 'Content-Transfer-Encoding=/^base64/Hi', - 'Content-Type=/^text/Bi', - 'Content-Transfer-Encoding=/^base64/Bi'), - description = 'Message text disguised using base64 encoding', - score = 0.0, - group = 'headers' -} -- 2.39.5