Skip to content
Permalink
Browse files Browse the repository at this point in the history
Security fixes for v1.0.469
Introduces sandbox policy to block extendable methods allowing arbitrary code execution
  • Loading branch information
daftspunk committed Sep 4, 2020
1 parent d49266a commit 4c650bb
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 0 deletions.
3 changes: 3 additions & 0 deletions modules/cms/classes/Controller.php
Expand Up @@ -15,6 +15,7 @@
use BackendAuth;
use Twig\Environment as TwigEnvironment;
use Twig\Cache\FilesystemCache as TwigCacheFilesystem;
use Twig\Extension\SandboxExtension;
use Cms\Twig\Loader as TwigLoader;
use Cms\Twig\DebugExtension;
use Cms\Twig\Extension as CmsTwigExtension;
Expand All @@ -23,6 +24,7 @@
use System\Helpers\View as ViewHelper;
use System\Classes\CombineAssets;
use System\Twig\Extension as SystemTwigExtension;
use System\Twig\SecurityPolicy;
use October\Rain\Exception\AjaxException;
use October\Rain\Exception\ValidationException;
use October\Rain\Parse\Bracket as TextParser;
Expand Down Expand Up @@ -608,6 +610,7 @@ protected function initTwigEnvironment()
$this->twig = new TwigEnvironment($this->loader, $options);
$this->twig->addExtension(new CmsTwigExtension($this));
$this->twig->addExtension(new SystemTwigExtension);
$this->twig->addExtension(new SandboxExtension(new SecurityPolicy, true));

if ($isDebugMode) {
$this->twig->addExtension(new DebugExtension($this));
Expand Down
3 changes: 3 additions & 0 deletions modules/system/ServiceProvider.php
Expand Up @@ -19,6 +19,7 @@
use System\Twig\Engine as TwigEngine;
use System\Twig\Loader as TwigLoader;
use System\Twig\Extension as TwigExtension;
use System\Twig\SecurityPolicy as TwigSecurityPolicy;
use System\Models\EventLog;
use System\Models\MailSetting;
use System\Classes\CombineAssets;
Expand All @@ -27,6 +28,7 @@
use October\Rain\Router\Helper as RouterHelper;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Schema;
use Twig\Extension\SandboxExtension;

class ServiceProvider extends ModuleServiceProvider
{
Expand Down Expand Up @@ -297,6 +299,7 @@ protected function registerTwigParser()
App::singleton('twig.environment', function ($app) {
$twig = new TwigEnvironment(new TwigLoader, ['auto_reload' => true]);
$twig->addExtension(new TwigExtension);
$twig->addExtension(new SandboxExtension(new TwigSecurityPolicy, true));
return $twig;
});

Expand Down
61 changes: 61 additions & 0 deletions modules/system/twig/SecurityPolicy.php
@@ -0,0 +1,61 @@
<?php namespace System\Twig;

use Twig\Markup;
use Twig\Template;
use Twig\Sandbox\SecurityPolicyInterface;
use Twig\Sandbox\SecurityNotAllowedMethodError;
use Twig\Sandbox\SecurityNotAllowedPropertyError;

/**
* SecurityPolicy globally blocks accessibility of certain methods and properties.
*
* @package october\system
* @author Alexey Bobkov, Samuel Georges
*/
final class SecurityPolicy implements SecurityPolicyInterface
{
protected $blockedProperties = [];

protected $blockedMethods = [
'addDynamicMethod',
'addDynamicProperty'
];

public function __construct()
{
$this->setBlockedMethods($this->blockedMethods);
}

public function setBlockedMethods(array $methods)

This comment has been minimized.

Copy link
@alxy

alxy Sep 7, 2020

Contributor

The argument $methods is not used inside this functions body? Is this on purpose? @daftspunk

This comment has been minimized.

Copy link
@LukeTowers

LukeTowers Sep 7, 2020

Contributor
{
foreach ($this->blockedMethods as $i => $m) {
$this->blockedMethods[$i] = strtr($m, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
}
}

public function checkSecurity($tags, $filters, $functions)
{
}

public function checkMethodAllowed($obj, $method)
{
if ($obj instanceof Template || $obj instanceof Markup) {
return;
}

$blockedMethod = strtr($method, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');

if (in_array($blockedMethod, $this->blockedMethods)) {
$class = get_class($obj);
throw new SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is blocked.', $method, $class), $class, $method);
}
}

public function checkPropertyAllowed($obj, $property)
{
if (in_array($property, $this->blockedProperties)) {
$class = get_class($obj);
throw new SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is blocked.', $property, $class), $class, $property);
}
}
}

0 comments on commit 4c650bb

Please sign in to comment.