Bug 5227 - Enhancement: Create a plugin to catch hosts trying to helo as me
Summary: Enhancement: Create a plugin to catch hosts trying to helo as me
Status: RESOLVED WONTFIX
Alias: None
Product: Spamassassin
Classification: Unclassified
Component: Rules (Eval Tests) (show other bugs)
Version: SVN Trunk (Latest Devel Version)
Hardware: Other other
: P5 enhancement
Target Milestone: Undefined
Assignee: SpamAssassin Developer Mailing List
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-12-07 08:10 UTC by Fred T
Modified: 2019-07-08 09:14 UTC (History)
3 users (show)



Attachment Type Modified Status Actions Submitter/CLA Status
Simple plugin text/plain None Matthias Leisi [HasCLA]
Detect HELO-forgery as "myself" text/plain None Matthias Leisi [HasCLA]
Detect HELO-forgery as "myself" (revised 1) text/plain None Matthias Leisi [HasCLA]

Note You need to log in before you can comment on or make changes to this bug.
Description Fred T 2006-12-07 08:10:38 UTC
It would be a nice test if we could specify the names of our servers and have a
test that would automatically add points if the sending party helo's with the
same name as the receiving party.

HostA is outside sender
HostB is spamassassin protected mail server.
When HostA connects to HostB and gives a helo of HostB or HostB's IP Address, it
would be nice to have a rule that could catch this.

One problem pointed out is how to determine the hostname or IP address of the
outside interface?  Possibly with a config item to allow the admin to specify
what the outside IP or DNS names are.

One issue I can think is when we have multiple servers using the same rule sets.
 I personally run 3 SA servers with the same set of rules, how would I setup
this configuration option to have it work on all 3 servers?

And last, we'd need to keep track of each server receiving mail in order to get
a proper mass-check of this rule, considering if mail in our corpus comes from
all sorts of various servers, how would we accurately measure this rules
accuracy through standard mass-checks etc?

It's a nice idea, but can it be implemented in a way that works for everyone?
Comment 1 Fred T 2006-12-08 07:03:34 UTC
From Matthias Leisi on users list:
I have cases where a machine legitimately HELOs as "myself"; in my
situation these cases are covered by trusted_networks or
internal_networks. Maybe eval:check_for_my_mx() should consider these
networks (or skip it's tests altogether if the connection came from one
of these networks); it may also need an actual exception list
('allowed_helo_as_myself').
Comment 2 Matthias Leisi 2006-12-10 04:37:02 UTC
Created attachment 3777 [details]
Simple plugin

Very simple plugin; not tested against the latest SA version from CVS but
against an older release (3.1.3).
Comment 3 Fred T 2006-12-13 14:45:09 UTC
This plugin looks promising, a quick test shows it hitting a few spam and no ham
yet.  After trying to tweak it some, I've run into a road block.  How do I
define more than one ip address or name to be used?  For in my setup, I have 3
IP addresses and 3 dns names that often get spoofed, I also see my domain name
spoofed as in:
helo mail.i-is.com
or
helo i-is.com
I'm trying to configure helo_my_names with multiple names, it doesn't seem to
take more than the last line I give it.  Should I use
helo_allow_all  ip1.x.x.x ip2.x.x.x ip3.x.x.x
or should I be using
helo_allow_all  ip1.x.x.x
helo_allow_all  ip2.x.x.x
etc?  Neither method seems to work yet.
If we can get this fixed, it'll be a real nice addition!!
Comment 4 Matthias Leisi 2006-12-13 14:50:24 UTC
> helo_allow_all  ip1.x.x.x
> helo_allow_all  ip2.x.x.x
> etc?  Neither method seems to work yet.

It doesn't work because I haven't figured out yet how to parse and/or read
multiple lines of the same config item ;)

> If we can get this fixed, it'll be a real nice addition!!

I'm pretty busy this week but I'll have some time over the weekend to improve on
that (also missing is a check against HELOing with IP addresses which I'd like
to add). 
Comment 5 Fred T 2006-12-14 08:18:59 UTC
Ok, thanks for responding, take a look at whitelist_from, trusted_networks or 
some other config items that already do this!
Comment 6 Fred T 2006-12-15 09:25:59 UTC
Somehow I managed to get this working on my own.  Not sure how good this is, I'm
not a perl dev.

Change:
type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING
to -->
type => $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST

add this sub:
sub _helo_is_in_list {
  my ($self, $list, $pms, $helo) = @_;
  $helo = lc $helo;
  foreach my $regexp (values %{$list}) {
    if ($helo =~ qr/$regexp/i) {
      dbg("HeloAsMyself: helo $helo matches regexp: $regexp");
      return 1;
    }
  }
  return 0;
}

Add this to check_for_helo_as_myself after my $ip = $pms->

return 1 if $self->_helo_is_in_list($pms->{conf}->{helo_my_names}, $pms, $helo);

Then a bunch of code can be removed or commented, it seems to be working as
expected now.
Comment 7 Fred T 2006-12-15 09:39:15 UTC
And to check for helo_is_my_ip I just added more config lines with my IP 
addresses as in:
helo_my_names  !66.51.152.240!

The ! is needed due to how it's matched against the headers.
Comment 8 Matthias Leisi 2006-12-19 01:14:12 UTC
Created attachment 3794 [details]
Detect HELO-forgery as "myself"

* Now tested against 3.1.7 on multiple environments
* Multiple "helo_allow_all" config items can be specified
* Multiple "helo_my_name" config items can be specified (renamed from
"helo_my_names")
* Using permessagestatus->{relays_untrusted} to determine the potentially
HELO-faking IP address, skipping ->{ip_private} addresses
* Now does three checks: exact match, HELO regex on "myself" and vice versa
Comment 9 Matthias Leisi 2006-12-20 01:52:04 UTC
Created attachment 3796 [details]
Detect HELO-forgery as "myself" (revised 1)

Change:

Line 206ff: If the potentially attacker-specified HELO string contains regex
metachars (eg "?"), we would receive errors or open an attack vector. Therefore
we skip the test if HELO contains anything but characters legal for a domain
(a-z0-9, ., -).

Also added a "Security Consideration" section to the POD doc.
Comment 10 Justin Mason 2006-12-20 04:48:42 UTC
if you change:

		} elsif ($myself =~ /.*$helo$/) {

to

		} elsif ($myself =~ /.*\Q$helo\E$/) {

that blocks the danger I think. (\Q, \E inhibit regexp metacharacters.)

taint mode is good for finding this stuff...
Comment 11 Matthias Leisi 2006-12-21 00:45:13 UTC
My own mass-check (see http://masscheck.dnswl.org/full-results.20061221) gives
the following result on this:

  MSECS    SPAM%     HAM%     S/O    RANK   SCORE  NAME
      0     6248      339    0.949   0.00    0.00  (all messages)
0.00000  94.8535   5.1465    0.949   0.00    0.00  (all messages as %)
[..]
  2.687   2.8169   0.2950    0.905   0.00    1.00  HELO_AS_MYSELF

The 0.295% ham (10 messages) are my own tests; however the 2.8% spam hits (175
messages) does not look too impressive. 

Regarding \Q..\E (comment #10): That's what I did first. While testing it became
clear that we don't have a valid HELO in cases where \Q..\E is necessary to
begin with, and hence we can not expect a match on "myself" anyway. So I decided
to skip the test completely. 

But it may make sense to have an actual rule to penlize obviously illegal HELOs
(or is there one already?). 
Comment 12 Henrik Krohns 2019-07-08 09:14:33 UTC
If not already blocking in MTA, one can simply use:

header FAKE_MY_HELO X-Spam-Relays-Untrusted =~ / helo=(?:\S+\.)?(?:mydomain\.com|mydomain2\.net) /i
header FAKE_MY_HELO_IP X-Spam-Relays-Untrusted =~ / helo=\S*\b12\.23\.34\.45\b/i

Closing.