CVE-2022-24953: Improper Neutralization of Argument Delimiters in a Command ('Argument Injection') (CWE-88)
value: The Crypt_GPG extension before 1.6.7 for PHP does not prevent additional options in GPG calls, which presents a risk for certain environments and GPG versions.
CWE description: The product constructs a string for a command to be executed by a separate component
in another control sphere, but it does not properly delimit the
intended arguments, options, or switches within that command string.
CVSS v3 base score: 5.3
Published: 2022-02-17T05:15Z
Repository: https://github.com/pear/Crypt_GPG
Language: PHP
Files changed: Crypt/GPG.php, Crypt/GPGAbstract.php
Commit date: 2022-02-10 08:50:44 +0100
Commit message: Insert the end-of-options marker before operation arguments.

This marker stops the parsing of additional options during external
calls to GPG. This behavior is unintended but its security impact is
dependent on the environment and the GPG version in use.

Diff: diff --git a/Crypt/GPG.php b/Crypt/GPG.php
index fda4c51..07a44c1 100644
--- a/Crypt/GPG.php
+++ b/Crypt/GPG.php
@@ -425,11 +425,11 @@ class Crypt_GPG extends Crypt_GPGAbstract
                 self::ERROR_KEY_NOT_FOUND,
                 $keyId
             );
         }
 
-        $operation = '--delete-key ' . escapeshellarg($fingerprint);
+        $operation = '--delete-key -- ' . escapeshellarg($fingerprint);
         $arguments = array(
             '--batch',
             '--yes'
         );
 
@@ -472,11 +472,11 @@ class Crypt_GPG extends Crypt_GPGAbstract
                 self::ERROR_KEY_NOT_FOUND,
                 $keyId
             );
         }
 
-        $operation = '--delete-secret-key ' . escapeshellarg($fingerprint);
+        $operation = '--delete-secret-key -- ' . escapeshellarg($fingerprint);
         $arguments = array(
             '--batch',
             '--yes'
         );
 
@@ -544,11 +544,11 @@ class Crypt_GPG extends Crypt_GPGAbstract
      *         exceptions occur.
      */
     public function getFingerprint($keyId, $format = self::FORMAT_NONE)
     {
         $output    = '';
-        $operation = '--list-keys ' . escapeshellarg($keyId);
+        $operation = '--list-keys -- ' . escapeshellarg($keyId);
         $arguments = array(
             '--with-colons',
             '--with-fingerprint'
         );
 
@@ -1462,11 +1462,11 @@ class Crypt_GPG extends Crypt_GPGAbstract
             );
         }
 
         $keyData   = '';
         $operation = $private ? '--export-secret-keys' : '--export';
-        $operation .= ' ' . escapeshellarg($fingerprint);
+        $operation .= ' -- ' . escapeshellarg($fingerprint);
         $arguments = $armor ? array('--armor') : array();
 
         $this->engine->reset();
         $this->engine->setPins($this->passphrases);
         $this->engine->setOutput($keyData);
diff --git a/Crypt/GPGAbstract.php b/Crypt/GPGAbstract.php
index c217967..efd6e42 100644
--- a/Crypt/GPGAbstract.php
+++ b/Crypt/GPGAbstract.php
@@ -332,11 +332,11 @@ abstract class Crypt_GPGAbstract
     {
         // get private key fingerprints
         if ($keyId == '') {
             $operation = '--list-secret-keys';
         } else {
-            $operation = '--utf8-strings --list-secret-keys ' . escapeshellarg($keyId);
+            $operation = '--utf8-strings --list-secret-keys -- ' . escapeshellarg($keyId);
         }
 
         // According to The file 'doc/DETAILS' in the GnuPG distribution, using
         // double '--with-fingerprint' also prints the fingerprint for subkeys.
         $arguments = array(
@@ -364,11 +364,11 @@ abstract class Crypt_GPGAbstract
 
         // get public keys
         if ($keyId == '') {
             $operation = '--list-public-keys';
         } else {
-            $operation = '--utf8-strings --list-public-keys ' . escapeshellarg($keyId);
+            $operation = '--utf8-strings --list-public-keys -- ' . escapeshellarg($keyId);
         }
 
         $output = '';
 
         $this->engine->reset();

Vulnerable code:         $operation = '--delete-key ' . escapeshellarg($fingerprint);
        $operation = '--delete-secret-key ' . escapeshellarg($fingerprint);
        $operation = '--list-keys ' . escapeshellarg($keyId);
        $operation .= ' ' . escapeshellarg($fingerprint);
            $operation = '--utf8-strings --list-secret-keys ' . escapeshellarg($keyId);
            $operation = '--utf8-strings --list-public-keys ' . escapeshellarg($keyId);
Fixed code:         $operation = '--delete-key -- ' . escapeshellarg($fingerprint);
        $operation = '--delete-secret-key -- ' . escapeshellarg($fingerprint);
        $operation = '--list-keys -- ' . escapeshellarg($keyId);
        $operation .= ' -- ' . escapeshellarg($fingerprint);
            $operation = '--utf8-strings --list-secret-keys -- ' . escapeshellarg($keyId);
            $operation = '--utf8-strings --list-public-keys -- ' . escapeshellarg($keyId);