Skip to content

Commit

Permalink
Merge pull request from GHSA-hv79-p62r-wg3p
Browse files Browse the repository at this point in the history
fix: Auth Remote Code execution
  • Loading branch information
jbrooksuk committed Oct 11, 2023
2 parents 2323e9c + 97a075c commit 6fb043e
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@
use CachetHQ\Cachet\Services\Dates\DateFactory;
use Carbon\Carbon;
use Illuminate\Contracts\Auth\Guard;

use Twig\Environment as Twig_Environment;
use Twig\Loader\ArrayLoader as Twig_Loader_Array;



/**
* This is the create incident command handler.
*
Expand All @@ -49,6 +52,8 @@ class CreateIncidentCommandHandler
*/
protected $dates;

protected $twigConfig;

/**
* Create a new create incident command handler instance.
*
Expand All @@ -61,6 +66,8 @@ public function __construct(Guard $auth, DateFactory $dates)
{
$this->auth = $auth;
$this->dates = $dates;

$this->twigConfig = config("cachet.twig");
}

/**
Expand Down Expand Up @@ -131,6 +138,34 @@ public function handle(CreateIncidentCommand $command)
return $incident;
}

protected function sandboxedTwigTemplateData(String $templateData) {

if (!$templateData) {
return "";
}

$policy = new \Twig\Sandbox\SecurityPolicy($this->twigConfig["tags"],
$this->twigConfig["filters"],
$this->twigConfig["methods"],
$this->twigConfig["props"],
$this->twigConfig["functions"]);

$sandbox = new \Twig\Extension\SandboxExtension($policy);

$templateBasicLoader = new Twig_Loader_Array([
'firstStageLoader' => $templateData
]);

$sandBoxBasicLoader = new Twig_Loader_Array([
'secondStageLoader' => '{% sandbox %}{% include "firstStageLoader" %} {% endsandbox %}'
]);

$hardenedLoader = new \Twig\Loader\ChainLoader([$templateBasicLoader, $sandBoxBasicLoader]);
$twig = new Twig_Environment($hardenedLoader);
$twig->addExtension($sandbox);
return $twig;
}

/**
* Compiles an incident template into an incident message.
*
Expand All @@ -141,8 +176,7 @@ public function handle(CreateIncidentCommand $command)
*/
protected function parseTemplate(IncidentTemplate $template, CreateIncidentCommand $command)
{
$env = new Twig_Environment(new Twig_Loader_Array([]));
$template = $env->createTemplate($template->template);
$template = $this->sandboxedTwigTemplateData($template->template);

$vars = array_merge($command->template_vars, [
'incident' => [
Expand All @@ -157,7 +191,7 @@ protected function parseTemplate(IncidentTemplate $template, CreateIncidentComma
'component_status' => $command->component_status,
],
]);

return $template->render($vars);
return $template->render('secondStageLoader', $vars);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ class UpdateIncidentCommandHandler
*/
protected $dates;

/**
* Twig configuration array.
*/
protected $twigConfig;

/**
* Create a new update incident command handler instance.
*
Expand All @@ -59,6 +64,8 @@ public function __construct(Guard $auth, DateFactory $dates)
{
$this->auth = $auth;
$this->dates = $dates;

$this->twigConfig = $twigConfig = config("cachet.twig");
}

/**
Expand Down Expand Up @@ -140,6 +147,28 @@ protected function filter(UpdateIncidentCommand $command)
});
}

protected function sandboxedTwigTemplateData(String $templateData) {
$policy = new \Twig\Sandbox\SecurityPolicy($this->twigConfig["tags"],
$this->twigConfig["filters"],
$this->twigConfig["methods"],
$this->twigConfig["props"],
$this->twigConfig["functions"]);
$sandbox = new \Twig\Extension\SandboxExtension($policy);

$templateBasicLoader = new \Twig\Loader\ArrayLoader([
'firstStageLoader' => $templateData
]);

$sandBoxBasicLoader = new \Twig\Loader\ArrayLoader([
'secondStageLoader' => '{% sandbox %}{% include "firstStageLoader" %} {% endsandbox %}'
]);

$hardenedLoader = new \Twig\Loader\ChainLoader([$templateBasicLoader, $sandBoxBasicLoader]);
$twig = new \Twig\Environment($hardenedLoader);
$twig->addExtension($sandbox);
return $twig;
}

/**
* Compiles an incident template into an incident message.
*
Expand All @@ -150,8 +179,7 @@ protected function filter(UpdateIncidentCommand $command)
*/
protected function parseTemplate(IncidentTemplate $template, UpdateIncidentCommand $command)
{
$env = new Twig_Environment(new Twig_Loader_Array([]));
$template = $env->createTemplate($template->template);
$template = $this->sandboxedTwigTemplateData($template->template);

$vars = array_merge($command->template_vars, [
'incident' => [
Expand All @@ -166,7 +194,7 @@ protected function parseTemplate(IncidentTemplate $template, UpdateIncidentComma
'component_status' => $command->component_status,
],
]);

return $template->render($vars);
return $template->render('secondStageLoader', $vars);
}
}
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"nexmo/client": "^1.5",
"pragmarx/google2fa": "^5.0",
"predis/predis": "^1.1",
"twig/twig": "^2.6"
"twig/twig": "^3.0"
},
"require-dev": {
"ext-sqlite3": "*",
Expand Down
18 changes: 18 additions & 0 deletions config/cachet.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,22 @@

'beacon' => env('CACHET_BEACON', true),


/*
|--------------------------------------------------------------------------
| Templates configurations
|--------------------------------------------------------------------------
|
| Security fix: now user can provide information which will be included to the Twig sandbox settings
|
| Default: Described below
|
*/
'twig' => [
'methods' => [],
'functions' => [],
'filters' => ['escape'],
'tags' => ['if'],
'props' => [],
]
];

0 comments on commit 6fb043e

Please sign in to comment.