annotate core/lib/Drupal/Core/Template/TwigSandboxPolicy.php @ 13:5fb285c0d0e3

Update Drupal core to 8.4.7 via Composer. Security update; I *think* we've been lucky to get away with this so far, as we don't support self-registration which seems to be used by the so-called "drupalgeddon 2" attack that 8.4.5 was vulnerable to.
author Chris Cannam
date Mon, 23 Apr 2018 09:33:26 +0100
parents 4c8ae668cc8c
children c2387f117808
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Core\Template;
Chris@0 4
Chris@0 5 use Drupal\Core\Site\Settings;
Chris@0 6
Chris@0 7 /**
Chris@0 8 * Default sandbox policy for Twig templates.
Chris@0 9 *
Chris@0 10 * Twig's sandbox extension is usually used to evaluate untrusted code by
Chris@0 11 * limiting access to potentially unsafe properties or methods. Since we do not
Chris@0 12 * use ViewModels when passing objects to Twig templates, we limit what those
Chris@0 13 * objects can do by whitelisting certain classes, method names, and method
Chris@0 14 * names with an allowed prefix. All object properties may be accessed.
Chris@0 15 */
Chris@0 16 class TwigSandboxPolicy implements \Twig_Sandbox_SecurityPolicyInterface {
Chris@0 17
Chris@0 18 /**
Chris@0 19 * An array of whitelisted methods in the form of methodName => TRUE.
Chris@0 20 */
Chris@0 21 protected $whitelisted_methods = NULL;
Chris@0 22
Chris@0 23 /**
Chris@0 24 * An array of whitelisted method prefixes -- any method starting with one of
Chris@0 25 * these prefixes will be allowed.
Chris@0 26 */
Chris@0 27 protected $whitelisted_prefixes = NULL;
Chris@0 28
Chris@0 29 /**
Chris@0 30 * An array of class names for which any method calls are allowed.
Chris@0 31 */
Chris@0 32 protected $whitelisted_classes = NULL;
Chris@0 33
Chris@0 34 /**
Chris@0 35 * Constructs a new TwigSandboxPolicy object.
Chris@0 36 */
Chris@0 37 public function __construct() {
Chris@0 38 // Allow settings.php to override our default whitelisted classes, methods,
Chris@0 39 // and prefixes.
Chris@0 40 $whitelisted_classes = Settings::get('twig_sandbox_whitelisted_classes', [
Chris@0 41 // Allow any operations on the Attribute object as it is intended to be
Chris@0 42 // changed from a Twig template, for example calling addClass().
Chris@0 43 'Drupal\Core\Template\Attribute',
Chris@0 44 ]);
Chris@0 45 // Flip the arrays so we can check using isset().
Chris@0 46 $this->whitelisted_classes = array_flip($whitelisted_classes);
Chris@0 47
Chris@0 48 $whitelisted_methods = Settings::get('twig_sandbox_whitelisted_methods', [
Chris@0 49 // Only allow idempotent methods.
Chris@0 50 'id',
Chris@0 51 'label',
Chris@0 52 'bundle',
Chris@0 53 'get',
Chris@0 54 '__toString',
Chris@0 55 'toString',
Chris@0 56 ]);
Chris@0 57 $this->whitelisted_methods = array_flip($whitelisted_methods);
Chris@0 58
Chris@0 59 $this->whitelisted_prefixes = Settings::get('twig_sandbox_whitelisted_prefixes', [
Chris@0 60 'get',
Chris@0 61 'has',
Chris@0 62 'is',
Chris@0 63 ]);
Chris@0 64 }
Chris@0 65
Chris@0 66 /**
Chris@0 67 * {@inheritdoc}
Chris@0 68 */
Chris@0 69 public function checkSecurity($tags, $filters, $functions) {}
Chris@0 70
Chris@0 71 /**
Chris@0 72 * {@inheritdoc}
Chris@0 73 */
Chris@0 74 public function checkPropertyAllowed($obj, $property) {}
Chris@0 75
Chris@0 76 /**
Chris@0 77 * {@inheritdoc}
Chris@0 78 */
Chris@0 79 public function checkMethodAllowed($obj, $method) {
Chris@0 80 foreach ($this->whitelisted_classes as $class => $key) {
Chris@0 81 if ($obj instanceof $class) {
Chris@0 82 return TRUE;
Chris@0 83 }
Chris@0 84 }
Chris@0 85
Chris@0 86 // Return quickly for an exact match of the method name.
Chris@0 87 if (isset($this->whitelisted_methods[$method])) {
Chris@0 88 return TRUE;
Chris@0 89 }
Chris@0 90
Chris@0 91 // If the method name starts with a whitelisted prefix, allow it.
Chris@0 92 // Note: strpos() is between 3x and 7x faster than preg_match in this case.
Chris@0 93 foreach ($this->whitelisted_prefixes as $prefix) {
Chris@0 94 if (strpos($method, $prefix) === 0) {
Chris@0 95 return TRUE;
Chris@0 96 }
Chris@0 97 }
Chris@0 98
Chris@0 99 throw new \Twig_Sandbox_SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj)));
Chris@0 100 }
Chris@0 101
Chris@0 102 }