CVE-2021-37708: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') (CWE-78)
value: Shopware is an open source eCommerce platform. Versions prior to 6.4.3.1 contain a command injection vulnerability in mail agent settings. Version 6.4.3.1 contains a patch. As workarounds for older versions of 6.1, 6.2, and 6.3, corresponding security measures are also available via a plugin.
CWE description: The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
CVSS v3 base score: 9.8
Published: 2021-08-16T20:15Z
Repository: https://github.com/shopware/platform
Language: PHP
Files changed: src/Core/Content/Mail/Service/MailerTransportFactory.php, src/Core/Content/Test/MailTemplate/Service/MailerTransportFactoryTest.php
Commit date: 2021-08-02 16:28:57 +0200
Commit message: NEXT-15669 - Improve mail configuration

Diff: diff --git a/src/Core/Content/Mail/Service/MailerTransportFactory.php b/src/Core/Content/Mail/Service/MailerTransportFactory.php
index 6b4ccac68d9..72400df9e78 100644
--- a/src/Core/Content/Mail/Service/MailerTransportFactory.php
+++ b/src/Core/Content/Mail/Service/MailerTransportFactory.php
@@ -51,11 +51,11 @@ class MailerTransportFactory extends Transport
 
         switch ($emailAgent) {
             case 'smtp':
                 return $this->createSmtpTransport($configService);
             case 'local':
-                return new SendmailTransport('/usr/sbin/sendmail ' . ($configService->getString('core.mailerSettings.sendMailOptions') ?: '-bs'));
+                return new SendmailTransport($this->getSendMailCommandLineArgument($configService));
             default:
                 throw new \RuntimeException(sprintf('Invalid mail agent given "%s"', $emailAgent));
         }
     }
 
@@ -84,6 +84,23 @@ class MailerTransportFactory extends Transport
                 return 'tls';
             default:
                 return null;
         }
     }
+
+    private function getSendMailCommandLineArgument(SystemConfigService $configService): string
+    {
+        $command = '/usr/sbin/sendmail ';
+
+        $option = $configService->getString('core.mailerSettings.sendMailOptions');
+
+        if ($option === '') {
+            $option = '-t';
+        }
+
+        if ($option !== '-bs' && $option !== '-t') {
+            throw new \RuntimeException(sprintf('Given sendmail option "%s" is invalid', $option));
+        }
+
+        return $command . $option;
+    }
 }
diff --git a/src/Core/Content/Test/MailTemplate/Service/MailerTransportFactoryTest.php b/src/Core/Content/Test/MailTemplate/Service/MailerTransportFactoryTest.php
index 013cb15ff64..8fbb9a20995 100644
--- a/src/Core/Content/Test/MailTemplate/Service/MailerTransportFactoryTest.php
+++ b/src/Core/Content/Test/MailTemplate/Service/MailerTransportFactoryTest.php
@@ -68,10 +68,29 @@ class MailerTransportFactoryTest extends TestCase
             ])
         );
 
         static::assertEquals(\get_class($original), \get_class($mailer));
     }
+
+    public function testFactoryWithLocalAndInvalidConfig(): void
+    {
+        $original = new SendmailTransport();
+
+        $factory = $this->getContainer()->get('mailer.transport_factory');
+
+        static::expectException(\RuntimeException::class);
+        static::expectExceptionMessage('Given sendmail option "-t && echo bla" is invalid');
+
+        $mailer = $factory->create(
+            new ConfigService([
+                'core.mailerSettings.emailAgent' => 'local',
+                'core.mailerSettings.sendMailOptions' => '-t && echo bla',
+            ])
+        );
+
+        static::assertEquals(\get_class($original), \get_class($mailer));
+    }
 }
 
 class ConfigService extends SystemConfigService
 {
     private $config;

Vulnerable code:                 return new SendmailTransport('/usr/sbin/sendmail ' . ($configService->getString('core.mailerSettings.sendMailOptions') ?: '-bs'));
Fixed code:                 return new SendmailTransport($this->getSendMailCommandLineArgument($configService));

    private function getSendMailCommandLineArgument(SystemConfigService $configService): string
    {
        $command = '/usr/sbin/sendmail ';

        $option = $configService->getString('core.mailerSettings.sendMailOptions');

        if ($option === '') {
            $option = '-t';
        }

        if ($option !== '-bs' && $option !== '-t') {
            throw new \RuntimeException(sprintf('Given sendmail option "%s" is invalid', $option));
        }

        return $command . $option;
    }

    public function testFactoryWithLocalAndInvalidConfig(): void
    {
        $original = new SendmailTransport();

        $factory = $this->getContainer()->get('mailer.transport_factory');

        static::expectException(\RuntimeException::class);
        static::expectExceptionMessage('Given sendmail option "-t && echo bla" is invalid');

        $mailer = $factory->create(
            new ConfigService([
                'core.mailerSettings.emailAgent' => 'local',
                'core.mailerSettings.sendMailOptions' => '-t && echo bla',
            ])
        );

        static::assertEquals(\get_class($original), \get_class($mailer));
    }