I’m currently facing an issue related to forged emails being sent from my server and I’m looking for a solution.
At the moment, I’m managing around 14,000 corporate email accounts. Unfortunately, some of my clients fall victim to phishing attacks, where they end up providing their email credentials to spammers. These spammers then use this information to send forged emails, where the “From” field in the email header is falsified, while the envelope contains the correct credentials.
Here’s an example of the script used by spammers:
<?php
$to = "[email protected]";
$subject = "Test forged email";
$message = "This is a test of sending a forged email.";
$headers = "From: [email protected]" . "\r\n" .
"Reply-To: [email protected]" . "\r\n" .
"X-Mailer: PHP/" . phpversion();
// Send email
if(mail($to, $subject, $message, $headers)) {
echo "Email sent successfully.";
} else {
echo "Failed to send the email.";
}
?>
They can send up to 500 emails like this using my server. I would like to know if there’s a way to configure Exim so that it only sends emails where the envelope sender matches the “From” address in the header, preventing this kind of abuse.
Edit conf file /etc/exim4/exim4.conf.template and add this rule to acl_check_data:
deny message = The envelope sender does not match the From header
condition = ${if !eq {$sender_address} {${address:$h_From:}}}
In context, it will look like this:
acl_check_data:
deny message = The envelope sender does not match the From header
condition = ${if !eq {$sender_address} {${address:$h_From:}}}
.ifdef CLAMD
deny message = Message contains a virus ($malware_name) and has been rejected
malware = */defer_ok
condition = ${if eq{$acl_m0}{yes}{yes}{no}}
.endif
.ifdef SPAMASSASSIN
[...]
Thank you very much. My Exim configuration is now:
acl_check_data:
deny message = The envelope sender does not match the From header
condition = ${if !eq {$sender_address} {${address:$h_From:}}}
.ifdef CLAMD
deny message = Message contains a virus ($malware_name) and has been rejected
malware = */defer_ok
condition = ${if eq{$acl_m0}{yes}{yes}{no}}
.endif
Unfortunately, it is still sending the email. Theoretically, this email should not be sent when I run the PHP script below, correct?
<?php
$to = "[email protected]";
$subject = "Test forged email";
$message = "This is a test of sending a forged email.";
$headers = "From: [email protected]" . "\r\n" .
"Reply-To: [email protected]" . "\r\n" .
"X-Mailer: PHP/" . phpversion();
// Send email
if(mail($to, $subject, $message, $headers)) {
echo "Email sent successfully.";
} else {
echo "Failed to send email.";
}
?>
I had tried a similar approach before, but it still allows the email to be sent.
Sorry for the confusion earlier. I was actually testing the code incorrectly by running it directly on the server, where it executes as the Exim root user and bypasses the configured rules. After correcting the test and running the code on my local machine, as shown below, the email was indeed not sent, as expected.
Thank you very much for your contribution. For anyone encountering a similar issue, here is the code I used for testing locally:
#!/bin/bash
# Email settings
SMTP_SERVER="mail.kingteste2.com.br"
SMTP_PORT="587"
SMTP_USER="[email protected]"
SMTP_PASS="7sdasdaasdas3"
FROM="[email protected]" # Forged sender
TO="[email protected]"
SUBJECT="Email Test"
BODY="This is a test email."
# Create a temporary file for the email body
EMAIL_FILE=$(mktemp)
cat <<EOF > "$EMAIL_FILE"
From: $FROM
To: $TO
Subject: $SUBJECT
$BODY
EOF
# Send the email using curl
curl --url "smtp://$SMTP_SERVER:$SMTP_PORT" \
--ssl-reqd \
--insecure \
--mail-from "$SMTP_USER" \
--mail-rcpt "$TO" \
--user "$SMTP_USER:$SMTP_PASS" \
-T "$EMAIL_FILE" \
-v
# Clean up the temporary file
rm "$EMAIL_FILE"
If anyone is experiencing a similar problem, you can use this code to test and check if the email sending is blocked as expected.