Command Injection Issue in Squirrelmail's G/PGP Encryption Plugin
25 Dec. 2003
Summary
Squirrelmail's G/PGP Encryption Plugin is "a general purpose encryption plugin for Squirrelmail". The plugin has been found to contain a vulnerability that allows remote attacker to cause the plugin to execute arbitrary commands.
NOTE: We do not believe that this theoretical vulnerability is exploitable.
Vulnerable systems:
* G/PGP Encryption Plugin version 1.1
Adding a ";command;" to the To: line of a newly created e-mail and then clicking "encrypt now" will execute the command as the Apache user.
Example:
By providing the following To address, you can test your system for the mentioned vulnerability ;echo "YO, dudes. Static analysis ain't rocket science." >> /tmp/message;.
Vulnerable code:
The gpg_encrypt_functions.php file contains the following command: // wrap it up by setting the recipients to the sender list using -r
// and redirect the output to stderr using 2>&1
$command .= " -r $send_to_list 2>&1";
Which is later exec() using: exec($command, $cyphertext, $returnval);
The sent_to_list variable is passed by the function's defining parameters: function gpg_encrypt($body,$send_to_list,$debug)
The file gpg_encrypt.php calls the function gpg_enrypt() by issuing: //call gpg_encrypt with the recipient list
$return = gpg_encrypt($body, $recipientlist ,$debug);
The recipientlist variable comes from: //call the address parsing function to return an array of addresses
$valid_addresses = gpg_parse_address ($send_to, $send_to_cc, $send_to_bcc, $debug);
// create the recipientlist string from the $valid_addresses array
$recipientlist = join (" -r ", $valid_addresses);
$recipientlist = $recipientlist;
The gpg_encrypt_functions.php file contains the gpg_parse_address function, which does address parsing: $abook = addressbook_init(false, true);
$rfc822_header = new Rfc822Header;
$rfc822_header->to = $rfc822_header->parseAddress($_POST['send_to'],
true,array(), '', $domain, array(&$abook,'lookup'));
$rfc822_header->cc = $rfc822_header->parseAddress($_POST['send_to_cc'],
true,array(), '',$domain,array(&$abook,'lookup'));
$rfc822_header->bcc = $rfc822_header->parseAddress($_POST['send_to_bcc'],
true,array(), '',$domain, array(&$abook,'lookup'));
Since parseAddress's 4th parameter is set to '' (empty) the function will not treat ';' as a new email ( the function is declared as parseAddress($address ,$ar ,$aAddress, $sGroup, $sHost, $lookup) ): case ';':
if ($sGroup) {
$aAddress[] = $this->createAddressObject($aStack,$aComment,$sEmail,$sGroup);
$oAddr = end($aAddress);
if(!$oAddr || ((isset($oAddr)) && !$oAddr->mailbox && !$oAddr->personal)) {
$sEmail = $sGroup . ':;';
}
$aAddress[] = $this->createAddressObject($aStack,$aComment,$sEmail,$sGroup);
$sGroup = '';
$aStack = $aComment = array();
break;
}
This means that the gpg program will execute with the commands we provide after the character ';' (Note some characters cannot be used in the commands specified, as they will be detected as an email address starting sign/ending sign).