From 6f8e6ac68b9aaab6aa1dcb15ce31cc19d52cadc3 Mon Sep 17 00:00:00 2001 From: Steve Freegard Date: Wed, 9 Nov 2016 23:04:18 +0000 Subject: [PATCH] Add compromised_host rules --- rules/regexp/compromised_hosts.lua | 190 +++++++++++++++++++++++++++++ rules/rspamd.lua | 1 + 2 files changed, 191 insertions(+) create mode 100644 rules/regexp/compromised_hosts.lua diff --git a/rules/regexp/compromised_hosts.lua b/rules/regexp/compromised_hosts.lua new file mode 100644 index 000000000..e5b483645 --- /dev/null +++ b/rules/regexp/compromised_hosts.lua @@ -0,0 +1,190 @@ +local reconf = config['regexp'] +local rspamd_regexp = require 'rspamd_regexp' + +reconf['HAS_PHPMAILER_SIG'] = { + re = "X-Mailer=/^PHPMailer/Hi || Content-Type=/boundary=\"b[123]_/Hi", + description = "PHPMailer signature", + group = "compromised_hosts" +} + +reconf['PHP_SCRIPT_ROOT'] = { + re = "X-PHP-Originating-Script=/^0:/Hi", + description = "PHP Script executed by root UID", + score = 2.0, + group = "compromised_hosts" +} + +reconf['HAS_X_POS'] = { + re = "header_exists('X-PHP-Originating-Script')", + description = "Has X-PHP-Originating-Script header", + group = "compromised_hosts" +} + +reconf['HAS_X_PHP_SCRIPT'] = { + re = "header_exists('X-PHP-Script')", + description = "Has X-PHP-Script header", + group = "compromised_hosts" +} + +-- X-Source: +-- X-Source-Args: /usr/sbin/proxyexec -q -d -s /var/run/proxyexec/cagefs.sock/socket /bin/cagefs.server +-- X-Source-Dir: silvianimberg.com:/public_html/wp-content/themes/ultimatum +reconf['HAS_X_SOURCE'] = { + re = "header_exists('X-Source') || header_exists('X-Source-Args') || header_exists('X-Source-Dir')", + description = "Has X-Source headers", + group = "compromised_hosts" +} + +-- X-Authenticated-Sender: accord.host-care.com: sales@cortaflex.si +rspamd_config.HAS_X_AS = { + callback = function (task) + local xas = task:get_header('X-Authenticated-Sender') + if not xas then return false end + local _,_,auth = xas:find('[^:]+:%s(.+)$') + if auth then + -- TODO: see if we can parse an e-mail address from auth + -- and see if it matches the from address or not + return true, auth + else + return true + end + end, + description = 'Has X-Authenticated-Sender header', + group = "compromised_hosts" +} + +-- X-Get-Message-Sender-Via: accord.host-care.com: authenticated_id: sales@cortaflex.si +rspamd_config.HAS_X_GMSV = { + callback = function (task) + local xgmsv = task:get_header('X-Get-Message-Sender-Via') + if not xgmsv then return false end + local _,_,auth = xgmsv:find('authenticated_id: (.+)$') + if auth then + -- TODO: see if we can parse an e-mail address from auth + -- and see if it matches the from address or not. + return true, auth + else + return true + end + end, + description = 'Has X-Get-Message-Sender-Via: header', + group = "compromised_hosts" +} + +-- X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +-- X-AntiAbuse: Primary Hostname - accord.host-care.com +-- X-AntiAbuse: Original Domain - swaney.com +-- X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +-- X-AntiAbuse: Sender Address Domain - dropbox.com +reconf['HAS_X_ANTIABUSE'] = { + re = "header_exists('X-AntiAbuse')", + description = "Has X-AntiAbuse headers", + group = "compromised_hosts" +} + +reconf['PHP_EVALD_CODE'] = { + re = "X-PHP-Script=/eval\\(\\)\\'d/Hi || X-PHP-Originating-Script=/eval\\(\\)\\'d/Hi", + description = "Message sent using eval'd PHP", + score = 5.0, + group = "compromised_hosts" +} + +reconf['HAS_WP_URI'] = { + re = '/\\/wp-[^\\/]+\\//Ui', + description = "Contains WordPress URIs", + group = "compromised_hosts" +} + +reconf['WP_COMPROMISED'] = { + re = '/\\/wp-(?!content|includes)[^\\/]+\\//Ui', + description = "URL that is pointing to a compromised WordPress installation", + score = 5.0, + group = "compromised_hosts" +} + +reconf['PHP_XPS_PATTERN'] = { + re = 'X-PHP-Script=/^[^\\. ]+\.[^\\.\\/ ]+\\/sendmail\\.php\\b/Hi', + description = "Message contains X-PHP-Script pattern", + score = 5.0, + group = "compromised_hosts" +} + +reconf['HAS_XAW'] = { + re = "header_exists('X-Authentication-Warning')", + description = "Has X-Authentication-Warning header", + group = "compromised_hosts" +} + +-- X-Authentication-Warning: localhost.localdomain: www-data set sender to info@globalstock.lv using -f +reconf['XAW_SERVICE_ACCT'] = { + re = "X-Authentication-Warning=/\\b(?:www-data|anonymous|ftp|apache|nobody|guest|nginx|web|www) set sender to\\b/Hi", + description = "Message originally from a service account", + score = 1.0, + group = "compromised_hosts" +} + +reconf['ENVFROM_SERVICE_ACCT'] = { + re = "check_smtp_data('from',/^(?:www-data|anonymous|ftp|apache|nobody|guest|nginx|web|www)@/i)", + description = "Envelope from is a service account", + score = 1.0, + group = "compromised_hosts" +} + +reconf['HIDDEN_SOURCE_OBJ'] = { + re = "X-PHP-Script=/\\/\\..+/Hi || X-PHP-Originating-Script=/(?:^\\d+:|\\/)\\..+/Hi || X-Source-Args=/\\/\\..+/Hi", + description = "UNIX hidden file/directory in path", + score = 2.0, + group = "compromised_hosts" +} + +reconf['URI_HIDDEN_PATH'] = { + re = "/\\/\\..+/U", + description = "URL contains a UNIX hidden file/directory", + score = 1.0, + group = "compromised_hosts" +} + +reconf['MID_RHS_WWW'] = { + re = "Message-Id=/@www\\./Hi", + description = "Message-ID from www host", + score = 0.5, + group = "compromised_hosts" +} + +rspamd_config.FROM_SERVICE_ACCT = { + callback = function (task) + local re = rspamd_regexp.create_cached('/^(?:www-data|anonymous|ftp|apache|nobody|guest|nginx|web|www)@/i'); + -- From + local from = task:get_from(2) + if (from and from[1]) then + if (re:match(from[1].addr)) then return true end + end + -- Sender + local sender = task:get_header('Sender') + if sender then + local s = util.parse_mail_address(sender) + if (s and s[1]) then + if (re:match(s[1].addr)) then return true end + end + end + -- Reply-To + local replyto = task:get_header('Reply-To') + if replyto then + local rt = util.parse_mail_address(replyto) + if (rt and rt[1]) then + if (re:match(rt[1].addr)) then return true end + end + end + end, + description = "Sender/From/Reply-To is a service account", + score = 1.0, + group = "compromised_hosts" +} + +reconf['WWW_DOT_DOMAIN'] = { + re = "From=/@www\\./Hi || Sender=/@www\\./Hi || Reply-To=/@www\\./Hi || check_smtp_data('from',/@www\\./i)", + description = "From/Sender/Reply-To or Envelope is @www.domain.com", + score = 0.5, + group = "compromised_hosts" +} + diff --git a/rules/rspamd.lua b/rules/rspamd.lua index a3cdc919b..086f81497 100644 --- a/rules/rspamd.lua +++ b/rules/rspamd.lua @@ -29,6 +29,7 @@ dofile(local_rules .. '/regexp/lotto.lua') dofile(local_rules .. '/regexp/fraud.lua') dofile(local_rules .. '/regexp/drugs.lua') dofile(local_rules .. '/regexp/upstream_spam_filters.lua') +dofile(local_rules .. '/regexp/compromised_hosts.lua') dofile(local_rules .. '/html.lua') dofile(local_rules .. '/misc.lua') dofile(local_rules .. '/http_headers.lua') -- 2.39.5