You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

compromised_hosts.lua 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. local reconf = config['regexp']
  2. local rspamd_regexp = require 'rspamd_regexp'
  3. local util = require 'rspamd_util'
  4. reconf['HAS_PHPMAILER_SIG'] = {
  5. re = "X-Mailer=/^PHPMailer/Hi || Content-Type=/boundary=\"b[123]_/Hi",
  6. description = "PHPMailer signature",
  7. group = "compromised_hosts"
  8. }
  9. reconf['PHP_SCRIPT_ROOT'] = {
  10. re = "X-PHP-Originating-Script=/^0:/Hi",
  11. description = "PHP Script executed by root UID",
  12. score = 2.0,
  13. group = "compromised_hosts"
  14. }
  15. reconf['HAS_X_POS'] = {
  16. re = "header_exists('X-PHP-Originating-Script')",
  17. description = "Has X-PHP-Originating-Script header",
  18. group = "compromised_hosts"
  19. }
  20. reconf['HAS_X_PHP_SCRIPT'] = {
  21. re = "header_exists('X-PHP-Script')",
  22. description = "Has X-PHP-Script header",
  23. group = "compromised_hosts"
  24. }
  25. -- X-Source:
  26. -- X-Source-Args: /usr/sbin/proxyexec -q -d -s /var/run/proxyexec/cagefs.sock/socket /bin/cagefs.server
  27. -- X-Source-Dir: silvianimberg.com:/public_html/wp-content/themes/ultimatum
  28. reconf['HAS_X_SOURCE'] = {
  29. re = "header_exists('X-Source') || header_exists('X-Source-Args') || header_exists('X-Source-Dir')",
  30. description = "Has X-Source headers",
  31. group = "compromised_hosts"
  32. }
  33. -- X-Authenticated-Sender: accord.host-care.com: sales@cortaflex.si
  34. rspamd_config.HAS_X_AS = {
  35. callback = function (task)
  36. local xas = task:get_header('X-Authenticated-Sender')
  37. if not xas then return false end
  38. local _,_,auth = xas:find('[^:]+:%s(.+)$')
  39. if auth then
  40. -- TODO: see if we can parse an e-mail address from auth
  41. -- and see if it matches the from address or not
  42. return true, auth
  43. else
  44. return true
  45. end
  46. end,
  47. description = 'Has X-Authenticated-Sender header',
  48. group = "compromised_hosts"
  49. }
  50. -- X-Get-Message-Sender-Via: accord.host-care.com: authenticated_id: sales@cortaflex.si
  51. rspamd_config.HAS_X_GMSV = {
  52. callback = function (task)
  53. local xgmsv = task:get_header('X-Get-Message-Sender-Via')
  54. if not xgmsv then return false end
  55. local _,_,auth = xgmsv:find('authenticated_id: (.+)$')
  56. if auth then
  57. -- TODO: see if we can parse an e-mail address from auth
  58. -- and see if it matches the from address or not.
  59. return true, auth
  60. else
  61. return true
  62. end
  63. end,
  64. description = 'Has X-Get-Message-Sender-Via: header',
  65. group = "compromised_hosts"
  66. }
  67. -- X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
  68. -- X-AntiAbuse: Primary Hostname - accord.host-care.com
  69. -- X-AntiAbuse: Original Domain - swaney.com
  70. -- X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12]
  71. -- X-AntiAbuse: Sender Address Domain - dropbox.com
  72. reconf['HAS_X_ANTIABUSE'] = {
  73. re = "header_exists('X-AntiAbuse')",
  74. description = "Has X-AntiAbuse headers",
  75. group = "compromised_hosts"
  76. }
  77. reconf['PHP_EVALD_CODE'] = {
  78. re = "X-PHP-Script=/eval\\(\\)\\'d/Hi || X-PHP-Originating-Script=/eval\\(\\)\\'d/Hi",
  79. description = "Message sent using eval'd PHP",
  80. score = 5.0,
  81. group = "compromised_hosts"
  82. }
  83. reconf['HAS_WP_URI'] = {
  84. re = '/\\/wp-[^\\/]+\\//Ui',
  85. description = "Contains WordPress URIs",
  86. group = "compromised_hosts"
  87. }
  88. reconf['WP_COMPROMISED'] = {
  89. re = '/\\/wp-(?!content|includes)[^\\/]+\\//Ui',
  90. description = "URL that is pointing to a compromised WordPress installation",
  91. score = 5.0,
  92. group = "compromised_hosts"
  93. }
  94. reconf['PHP_XPS_PATTERN'] = {
  95. re = 'X-PHP-Script=/^[^\\. ]+\\.[^\\.\\/ ]+\\/sendmail\\.php\\b/Hi',
  96. description = "Message contains X-PHP-Script pattern",
  97. score = 5.0,
  98. group = "compromised_hosts"
  99. }
  100. reconf['HAS_XAW'] = {
  101. re = "header_exists('X-Authentication-Warning')",
  102. description = "Has X-Authentication-Warning header",
  103. group = "compromised_hosts"
  104. }
  105. -- X-Authentication-Warning: localhost.localdomain: www-data set sender to info@globalstock.lv using -f
  106. reconf['XAW_SERVICE_ACCT'] = {
  107. re = "X-Authentication-Warning=/\\b(?:www-data|anonymous|ftp|apache|nobody|guest|nginx|web|www) set sender to\\b/Hi",
  108. description = "Message originally from a service account",
  109. score = 1.0,
  110. group = "compromised_hosts"
  111. }
  112. reconf['ENVFROM_SERVICE_ACCT'] = {
  113. re = "check_smtp_data('from',/^(?:www-data|anonymous|ftp|apache|nobody|guest|nginx|web|www)@/i)",
  114. description = "Envelope from is a service account",
  115. score = 1.0,
  116. group = "compromised_hosts"
  117. }
  118. reconf['HIDDEN_SOURCE_OBJ'] = {
  119. re = "X-PHP-Script=/\\/\\..+/Hi || X-PHP-Originating-Script=/(?:^\\d+:|\\/)\\..+/Hi || X-Source-Args=/\\/\\..+/Hi",
  120. description = "UNIX hidden file/directory in path",
  121. score = 2.0,
  122. group = "compromised_hosts"
  123. }
  124. reconf['URI_HIDDEN_PATH'] = {
  125. re = "/\\/\\..+/U",
  126. description = "URL contains a UNIX hidden file/directory",
  127. score = 1.0,
  128. group = "compromised_hosts"
  129. }
  130. reconf['MID_RHS_WWW'] = {
  131. re = "Message-Id=/@www\\./Hi",
  132. description = "Message-ID from www host",
  133. score = 0.5,
  134. group = "compromised_hosts"
  135. }
  136. rspamd_config.FROM_SERVICE_ACCT = {
  137. callback = function (task)
  138. local re = rspamd_regexp.create_cached('/^(?:www-data|anonymous|ftp|apache|nobody|guest|nginx|web|www)@/i');
  139. -- From
  140. local from = task:get_from(2)
  141. if (from and from[1]) then
  142. if (re:match(from[1].addr)) then return true end
  143. end
  144. -- Sender
  145. local sender = task:get_header('Sender')
  146. if sender then
  147. local s = util.parse_mail_address(sender)
  148. if (s and s[1]) then
  149. if (re:match(s[1].addr)) then return true end
  150. end
  151. end
  152. -- Reply-To
  153. local replyto = task:get_header('Reply-To')
  154. if replyto then
  155. local rt = util.parse_mail_address(replyto)
  156. if (rt and rt[1]) then
  157. if (re:match(rt[1].addr)) then return true end
  158. end
  159. end
  160. end,
  161. description = "Sender/From/Reply-To is a service account",
  162. score = 1.0,
  163. group = "compromised_hosts"
  164. }
  165. reconf['WWW_DOT_DOMAIN'] = {
  166. re = "From=/@www\\./Hi || Sender=/@www\\./Hi || Reply-To=/@www\\./Hi || check_smtp_data('from',/@www\\./i)",
  167. description = "From/Sender/Reply-To or Envelope is @www.domain.com",
  168. score = 0.5,
  169. group = "compromised_hosts"
  170. }