Permalink
Browse files

Fix another potential security vector

  • Loading branch information...
1 parent 6d0e085 commit 537a811a09579be1a34b32325e9669069b38d531 Andy Thompson committed with weierophinney Sep 23, 2011
@@ -73,19 +73,6 @@ public function render(array $tokens, $view, array $partials = null)
$renderer = $this;
$inLoop = false;
- if (is_object($view)) {
- // If we have an object, get a list of properties and methods,
- // giving methods precedence.
- $props = get_object_vars($view);
- foreach (get_class_methods($view) as $method) {
- if ('__' == substr($method, 0, 2)) {
- // Omit magic methods
- continue;
- }
- $props[$method] = array($view, $method);
- }
- $view = $props;
- }
if (is_scalar($view)) {
// Iteration over lists will sometimes involve scalars
$inLoop = true;
@@ -111,7 +98,7 @@ public function render(array $tokens, $view, array $partials = null)
if (is_scalar($value)) {
$value = ('' === $value) ? '' : $this->escape($value);
} else {
- $pragmaView = array_merge($view, array($data => $value));
+ $pragmaView = array($data => $value);
if ($test = $this->handlePragmas($type, $data, $pragmaView)) {
$value = $test;
} else {
@@ -363,10 +350,9 @@ public function getValue($key, $view)
return '';
}
if (is_object($view)) {
- if (isset($view->$key)) {
- if (is_callable($view->$key) && $this->isValidCallback($view->$key)) {
- return call_user_func($view->$key);
- }
+ if (method_exists($view, $key)) {
+ return call_user_func(array($view, $key));
+ } else if (isset($view->$key)) {
return $view->$key;
}
return '';
@@ -467,21 +453,13 @@ protected function handlePragmas($token, $data, $view)
*/
protected function isValidCallback($callback)
{
- if (is_string($callback)) {
- if (strstr($callback, '::')) {
- // Referencing a static method call
- return true;
- }
- if (strstr($callback, '\\')) {
- // Referencing a namespaced function
- return true;
- }
-
- // For security purposes, we don't want to call global functions
+ if (is_string($callback) || is_array($callback)) {
+ // For security purposes, we don't want to call anything that isn't
+ // an object callback
return false;
}
- // Object or array callback -- always okay
+ // Object callback -- always okay
return true;
}
}
@@ -12,6 +12,8 @@
/** @namespace */
namespace PhlyTest\Mustache;
+use Phly\Mustache\Pragma\ImplicitIterator;
+
use Phly\Mustache\Mustache,
Phly\Mustache\Pragma;
@@ -573,4 +575,25 @@ public function testObjectPropertiesThatReferToPHPBuiltInsShouldNotCallThem()
$test = $this->mustache->render('template-referencing-php-function', $model);
$this->assertEquals('time', trim($test));
}
+
+ /**
+ * @group injection-issues
+ */
+ public function testArrayValuesThatReferToStaticMethodsShouldNotCallThem()
+ {
+ $model = array('message' => 'DateTime::createFromFormat');
+ $test = $this->mustache->render('template-referencing-php-function', $model);
+ $this->assertEquals('DateTime::createFromFormat', trim($test));
+ }
+
+ /**
+ * @group injection-issues
+ */
+ public function testArrayValuesThatReferToStaticMethodsInArraySyntaxShouldNotCallThem()
+ {
+ $model = array('section' => array('DateTime', 'createFromFormat'));
+ $this->mustache->getRenderer()->addPragma(new ImplicitIterator());
+ $test = $this->mustache->render('template-referencing-static-function', $model);
+ $this->assertEquals("DateTime\ncreateFromFormat", trim($test));
+ }
}
@@ -0,0 +1,4 @@
+{{%IMPLICIT-ITERATOR}}
+{{#section}}
+{{.}}
+{{/section}}

0 comments on commit 537a811

Please sign in to comment.