Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unauthenticated email accepted #286

Open
rimas-kudelis opened this issue Jan 23, 2024 · 10 comments
Open

Unauthenticated email accepted #286

rimas-kudelis opened this issue Jan 23, 2024 · 10 comments

Comments

@rimas-kudelis
Copy link
Collaborator

rimas-kudelis commented Jan 23, 2024

Back in October, I received a funny email in which some great hacker alleged that they had taken over my home network, my mailbox, my everything else, and even caught me on webcam jerking of.

What I found really interesting about that email is that is had my own email address in the From field. I really doubt that the great hacker actually had my credentials, so I suspect that there's a bug somewhere which lets unauthenticated email through if it targets a local mailbox. Would be nice to investigate.

Sadly, I haven't preserved logs from back then. But it should be easy enough to replicate using Telnet.

@ezbik
Copy link

ezbik commented Jan 23, 2024

Solution would be:

If sender domain is a local domain and email was received without smtp authentication - it is subject to antispam (spamassasin).

@runout-at
Copy link
Contributor

In /acl/30_exim4-config_check_mail I did add an ACL which checks for the sender domains (except if mail comes from my local IP ranges). Not sure if this targets the same szenario you have.

drop
  message = The sending mailserver was classified as backscatterer. \
              The sender domain $sender_address_domain is the same as a local domain.
  !authenticated = *
  !senders = :
  sender_domains = : +local_domains : +relay_to_domains
  !hosts = <; 10.0.0.0/16 ; localhost ; 127.0.0.1 ; 2001:db8::/32
  logwrite = :main,reject: REJECTED - sender domain $sender_address is the same as a local domain. RCPT: $local_part_data@$domain_data

I you use this, make sure to have proper IP ranges in the !hosts line.

@rimas-kudelis
Copy link
Collaborator Author

rimas-kudelis commented Jan 24, 2024

drop
message = The sending mailserver was classified as backscatterer.
The sender domain $sender_address_domain is the same as a local domain.
!authenticated = *
!senders = :
sender_domains = : +local_domains : +relay_to_domains
!hosts = <; 10.0.0.0/16 ; localhost ; 127.0.0.1 ; 2001:db8::/32
logwrite = :main,reject: REJECTED - sender domain $sender_address is the same as a local domain. RCPT: $local_part_data@$domain_data

I get why you would want and even need an exception for local IPs, but why the exception for local networks though?

I'd probably just use !host @[] instead.

Also that logwrite line seems like a copy-paste error.

@runout-at
Copy link
Contributor

You are right. !hosts line could be omitted completely. This comes from a time when I had clients (monitoring) on the internal networks which had problems with authentication and I didn't want to exclude each IP separately.

Why do you think the logwrite line is an error?

@rimas-kudelis
Copy link
Collaborator Author

rimas-kudelis commented Jan 24, 2024

You are right. !hosts line could be omitted completely. This comes from a time when I had clients (monitoring) on the internal networks which had problems with authentication and I didn't want to exclude each IP separately.

I guess it could be omitted, assuming emails from localhost are accepted beforehand. Otherwise wouldn't they be rejected by this ACL?

EDIT: nope! Commenting it out causes messages to be rejected even when they originate from localhost.

Why do you think the logwrite line is an error?

Now that I read it again, I take these words back. However, I'd probably write these messages differently.

The message mentions backscattering, but, based on the article in Wikipedia, I'd say backscatter is a different issue than this. I think I'd rather reject the message with the standard non-customized message instead (550 relay not permitted), or use something like "local users must always authenticate before sending mail".

And what the logwrite line says is not an invalid state by itself. It's invalid because that local user has not authenticated. I guess I would just let Exim reuse the message here.

BTW, I enabled SPF checking on my server (apparently it was off until now, along with some other checks), and that was enough for my case, because I use strict SPF rules on my domains. Still I think it would make sense for us to ship this ACL too. And it's tempting for me to go set it up for myself too. Gonna do it right now. :)

@rimas-kudelis
Copy link
Collaborator Author

rimas-kudelis commented Jan 24, 2024

So, I set it up and it works, and looks like this:

acl_check_mail:

  deny
    message = local users must authenticate before sending mail
    !authenticated = *
    !senders = :
    sender_domains = : +local_domains : +relay_to_domains
    # The !hosts line below allows sending emails from local domains
    # on local interfaces without authenticating first.
    # Comment it out if that is not desired.
    !hosts = @[]

  accept

But now it got me thinking whether this is actually the right thing to do... If my SPF policy prohibits anyone but my own server to send emails from me, this already works. On the other hand, if that policy allows anyone to send emails on my behalf, shouldn't my own server accept them? 🤔

@runout-at
Copy link
Contributor

Ok. thx for the feedback! And yes, at least !hosts will need something.

I believe in "SPF is broken by design" (but please, no discussion about that religion). I just configure it because otherwise I would have a lot of problems with other providers.

@rimas-kudelis
Copy link
Collaborator Author

Hmm, weird, I thought I'd copy (and later move) the stock SPF check from 30_exim4-config_check_rcpt to 30_exim4-config_check_mail to reject emails that fail SPF right after MAIL FROM instead of waiting for RCPT TO.

But then that check rejects my own emails even if I authenticate first. Which kinda makes sense since there are no exceptions for authenticated users in that check.

However, if it stays in check_rcpt then it doesn't reject my emails after authentication. I wonder why.

@runout-at
Copy link
Contributor

AFAIR there has been a change in the Debian config in the last years and Debian-Exim uses libspf2.
It should be sufficient to enable it in the config and as I don't use/trust SPF I didn't mess around with it:

  • main/00_local_listmacrosdefs
#CHECK_RCPT_SPF = true
#_HAVE_SPF = true

I don't know why there are two settings for that.

I think I use the original file from the Debian bookworm and SPF check is in

  • acl/30_exim4-config_check_rcpt
  .ifdef CHECK_RCPT_SPF
  .ifdef _HAVE_SPF
  deny
    !acl = acl_local_deny_exceptions
    spf = fail
    message = [SPF] $sender_host_address is not allowed to send mail from \
              ${if def:sender_address_domain {$sender_address_domain}{$sender_helo_name}}.
    log_message = SPF check failed.

  defer
    !acl = acl_local_deny_exceptions
    spf = temperror
    message = Temporary DNS error while checking SPF record.  Try again later.
    
  warn
    spf = pass:softfail:neutral:permerror
    add_header = :at_start:$spf_received
  .endif
  .endif

@rimas-kudelis
Copy link
Collaborator Author

AFAIR there has been a change in the Debian config in the last years and Debian-Exim uses libspf2. It should be sufficient to enable it in the config and as I don't use/trust SPF I didn't mess around with it:

* main/00_local_listmacrosdefs
#CHECK_RCPT_SPF = true
#_HAVE_SPF = true

I don't know why there are two settings for that.

I think I use the original file from the Debian bookworm and SPF check is in

* acl/30_exim4-config_check_rcpt
  .ifdef CHECK_RCPT_SPF
  .ifdef _HAVE_SPF
  deny
    !acl = acl_local_deny_exceptions
    spf = fail
    message = [SPF] $sender_host_address is not allowed to send mail from \
              ${if def:sender_address_domain {$sender_address_domain}{$sender_helo_name}}.
    log_message = SPF check failed.

  defer
    !acl = acl_local_deny_exceptions
    spf = temperror
    message = Temporary DNS error while checking SPF record.  Try again later.
    
  warn
    spf = pass:softfail:neutral:permerror
    add_header = :at_start:$spf_received
  .endif
  .endif

That's the method I was talking about. I'm somewhat surprised that this check is placed in acl/30_exim4-config_check_rcpt and not in acl/30_exim4-config_check_mail though, because it checks sender, not recipient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants