Catch exceptions during argument sanitization in sanitizeStacktrace()
authorTim Düsterhus <duesterhus@woltlab.com>
Wed, 5 May 2021 14:49:00 +0000 (16:49 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Wed, 5 May 2021 14:49:00 +0000 (16:49 +0200)
The sanitization logic is somewhat fragile. Redact all arguments of the current
stack frame if some error occurs to fail closed.

wcfsetup/install/files/lib/core.functions.php

index 3cecacd3ba2789d1fbdb2a15aad868f5ef9a2730..d8466d0e8fcf03a7faefac9a95ab45744569d4a1 100644 (file)
@@ -716,48 +716,54 @@ EXPLANATION;
                        if (!isset($item['type'])) $item['type'] = '';
                        if (!isset($item['args'])) $item['args'] = [];
 
-                       if (!empty($item['args'])) {
-                               if ($item['class']) {
-                                       $function = new \ReflectionMethod($item['class'], $item['function']);
-                               }
-                               else {
-                                       $function = new \ReflectionFunction($item['function']);
-                               }
-
-                               $parameters = $function->getParameters();
-                               $i = 0;
-                               foreach ($parameters as $parameter) {
-                                       $isSensitive = false;
-                                       if (
-                                               \method_exists($parameter, 'getAttributes')
-                                               && !empty($parameter->getAttributes(\wcf\SensitiveArgument::class))
-                                       ) {
-                                               $isSensitive = true;
+                       try {
+                               if (!empty($item['args'])) {
+                                       if ($item['class']) {
+                                               $function = new \ReflectionMethod($item['class'], $item['function']);
                                        }
-                                       if (\preg_match(
-                                               '/(?:^(?:password|passphrase|secret)|(?:Password|Passphrase|Secret))/',
-                                               $parameter->getName()
-                                       )) {
-                                               $isSensitive = true;
+                                       else {
+                                               $function = new \ReflectionFunction($item['function']);
                                        }
 
-                                       if ($isSensitive && isset($item['args'][$i])) {
-                                               $item['args'][$i] = '[redacted]';
+                                       $parameters = $function->getParameters();
+                                       $i = 0;
+                                       foreach ($parameters as $parameter) {
+                                               $isSensitive = false;
+                                               if (
+                                                       \method_exists($parameter, 'getAttributes')
+                                                       && !empty($parameter->getAttributes(\wcf\SensitiveArgument::class))
+                                               ) {
+                                                       $isSensitive = true;
+                                               }
+                                               if (\preg_match(
+                                                       '/(?:^(?:password|passphrase|secret)|(?:Password|Passphrase|Secret))/',
+                                                       $parameter->getName()
+                                               )) {
+                                                       $isSensitive = true;
+                                               }
+
+                                               if ($isSensitive && isset($item['args'][$i])) {
+                                                       $item['args'][$i] = '[redacted]';
+                                               }
+                                               $i++;
                                        }
-                                       $i++;
-                               }
-                               
-                               // strip database credentials
-                               if (
-                                       preg_match('~\\\\?wcf\\\\system\\\\database\\\\[a-zA-Z]*Database~', $item['class'])
-                                       || $item['class'] === 'PDO'
-                               ) {
-                                       if ($item['function'] === '__construct') {
-                                               $item['args'] = array_map(function () {
-                                                       return '[redacted]';
-                                               }, $item['args']);
+                                       
+                                       // strip database credentials
+                                       if (
+                                               preg_match('~\\\\?wcf\\\\system\\\\database\\\\[a-zA-Z]*Database~', $item['class'])
+                                               || $item['class'] === 'PDO'
+                                       ) {
+                                               if ($item['function'] === '__construct') {
+                                                       $item['args'] = array_map(function () {
+                                                               return '[redacted]';
+                                                       }, $item['args']);
+                                               }
                                        }
                                }
+                       } catch (\Throwable $e) {
+                               $item['args'] = array_map(function () {
+                                       return '[error_during_sanitization]';
+                               }, $item['args']);
                        }
                        
                        if (!$ignorePaths) {