mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-06 11:24:27 +02:00
update securitytests
This commit is contained in:
@@ -24,13 +24,15 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
$this->smarty->enableSecurity();
|
$this->smarty->enableSecurity();
|
||||||
$this->smartyBC->setForceCompile(true);
|
$this->smartyBC->setForceCompile(true);
|
||||||
$this->smartyBC->enableSecurity();
|
$this->smartyBC->enableSecurity();
|
||||||
$this->cleanDir($this->smarty->getCacheDir());
|
}
|
||||||
$this->cleanDir($this->smarty->getCompileDir());
|
public function testInit()
|
||||||
|
{
|
||||||
|
$this->cleanDirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test that security is loaded
|
* test that security is loaded
|
||||||
*/
|
' *'/
|
||||||
public function testSecurityReenable()
|
public function testSecurityReenable()
|
||||||
{
|
{
|
||||||
$this->smarty->disableSecurity();
|
$this->smarty->disableSecurity();
|
||||||
@@ -40,185 +42,161 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
$this->smarty->enableSecurity('Security');
|
$this->smarty->enableSecurity('Security');
|
||||||
$this->smarty->fetch('helloworld.tpl');
|
$this->smarty->fetch('helloworld.tpl');
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* test that security is loaded
|
* test that security is loaded
|
||||||
*/
|
*/
|
||||||
public function testSecurityLoaded()
|
public function testSecurityLoaded()
|
||||||
{
|
{
|
||||||
$this->assertTrue(is_object($this->smarty->security_policy));
|
$this->assertTrue(is_object($this->smarty->security_policy));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test trusted PHP function
|
* test trusted PHP function
|
||||||
*/
|
*/
|
||||||
public function testTrustedPHPFunction()
|
public function testTrustedPHPFunction()
|
||||||
{
|
{
|
||||||
$this->assertEquals("5", $this->smarty->fetch('eval:{assign var=foo value=[1,2,3,4,5]}{count($foo)}'));
|
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test not trusted PHP function
|
* test not trusted PHP function
|
||||||
*/
|
* @expectedException SmartyException
|
||||||
|
* @expectedExceptionMessage PHP function 'count' not allowed by security setting
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
*/
|
||||||
public function testNotTrustedPHPFunction()
|
public function testNotTrustedPHPFunction()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->php_functions = array('null');
|
$this->smarty->security_policy->php_functions = array('null');
|
||||||
try {
|
$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}');
|
||||||
$this->smarty->fetch('eval:{assign var=foo value=[1,2,3,4,5]}{count($foo)}');
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
$this->assertContains(htmlentities("PHP function 'count' not allowed by security setting"), $e->getMessage());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->fail('Exception for not trusted modifier has not been raised.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test not trusted PHP function at disabled security
|
* test not trusted PHP function at disabled security
|
||||||
*/
|
*/
|
||||||
public function testDisabledTrustedPHPFunction()
|
public function testDisabledTrustedPHPFunction()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->php_functions = array('null');
|
$this->smarty->security_policy->php_functions = array('null');
|
||||||
$this->smarty->disableSecurity();
|
$this->smarty->disableSecurity();
|
||||||
$this->assertEquals("5", $this->smarty->fetch('eval:{assign var=foo value=[1,2,3,4,5]}{count($foo)}'));
|
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test trusted modifier
|
* test trusted modifier
|
||||||
*/
|
*/
|
||||||
public function testTrustedModifier()
|
public function testTrustedModifier()
|
||||||
{
|
{
|
||||||
$this->assertEquals("5", $this->smarty->fetch('eval:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}'));
|
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test not trusted modifier
|
* test not trusted modifier
|
||||||
*/
|
* @expectedException SmartyException
|
||||||
|
* @expectedExceptionMessage modifier 'count' not allowed by security setting
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
*/
|
||||||
public function testNotTrustedModifier()
|
public function testNotTrustedModifier()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->php_modifiers = array('null');
|
$this->smarty->security_policy->php_modifiers = array('null');
|
||||||
try {
|
$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}');
|
||||||
$this->smarty->fetch('eval:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}');
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
$this->assertContains(htmlentities("modifier 'count' not allowed by security setting"), $e->getMessage());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->fail('Exception for not trusted modifier has not been raised.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test not trusted modifier at disabled security
|
* test not trusted modifier at disabled security
|
||||||
*/
|
*/
|
||||||
public function testDisabledTrustedModifier()
|
public function testDisabledTrustedModifier()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->php_modifiers = array('null');
|
$this->smarty->security_policy->php_modifiers = array('null');
|
||||||
$this->smarty->disableSecurity();
|
$this->smarty->disableSecurity();
|
||||||
$this->assertEquals("5", $this->smarty->fetch('eval:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}'));
|
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test allowed tags
|
* test allowed tags
|
||||||
*/
|
*/
|
||||||
public function testAllowedTags1()
|
public function testAllowedTags1()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->allowed_tags = array('counter');
|
$this->smarty->security_policy->allowed_tags = array('counter');
|
||||||
$this->assertEquals("1", $this->smarty->fetch('eval:{counter start=1}'));
|
$this->assertEquals("1", $this->smarty->fetch('string:{counter start=1}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test not allowed tag
|
* test not allowed tag
|
||||||
*/
|
* @expectedException SmartyException
|
||||||
|
* @expectedExceptionMessage tag 'cycle' not allowed by security setting
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
*/
|
||||||
public function testNotAllowedTags2()
|
public function testNotAllowedTags2()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->allowed_tags = array('counter');
|
$this->smarty->security_policy->allowed_tags = array('counter');
|
||||||
try {
|
$this->smarty->fetch('string:{counter}{cycle values="1,2"}');
|
||||||
$this->smarty->fetch('eval:{counter}{cycle values="1,2"}');
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
$this->assertContains(htmlentities("tag 'cycle' not allowed by security setting"), $e->getMessage());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->fail('Exception for not allowed tag has not been raised.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test disabled tag
|
* test disabled tag
|
||||||
*/
|
* @expectedException SmartyException
|
||||||
|
* @expectedExceptionMessage tag 'cycle' disabled by security setting
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
*/
|
||||||
public function testDisabledTags()
|
public function testDisabledTags()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->disabled_tags = array('cycle');
|
$this->smarty->security_policy->disabled_tags = array('cycle');
|
||||||
try {
|
$this->smarty->fetch('string:{counter}{cycle values="1,2"}');
|
||||||
$this->smarty->fetch('eval:{counter}{cycle values="1,2"}');
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
$this->assertContains(htmlentities("tag 'cycle' disabled by security setting"), $e->getMessage());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->fail('Exception for disabled tag has not been raised.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test allowed modifier
|
* test allowed modifier
|
||||||
*/
|
*/
|
||||||
public function testAllowedModifier1()
|
public function testAllowedModifier1()
|
||||||
{
|
{
|
||||||
error_reporting(E_ALL & E_STRICT);
|
error_reporting(E_ALL & E_STRICT);
|
||||||
$this->smarty->security_policy->allowed_modifiers = array('capitalize');
|
$this->smarty->security_policy->allowed_modifiers = array('capitalize');
|
||||||
$this->assertEquals("Hello World", $this->smarty->fetch('eval:{"hello world"|capitalize}'));
|
$this->assertEquals("Hello World", $this->smarty->fetch('string:{"hello world"|capitalize}'));
|
||||||
error_reporting(E_ALL | E_STRICT);
|
error_reporting(E_ALL | E_STRICT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAllowedModifier2()
|
public function testAllowedModifier2()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->allowed_modifiers = array('upper');
|
$this->smarty->security_policy->allowed_modifiers = array('upper');
|
||||||
$this->assertEquals("HELLO WORLD", $this->smarty->fetch('eval:{"hello world"|upper}'));
|
$this->assertEquals("HELLO WORLD", $this->smarty->fetch('string:{"hello world"|upper}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test not allowed modifier
|
* test not allowed modifier
|
||||||
*/
|
* @expectedException SmartyException
|
||||||
|
* @expectedExceptionMessage modifier 'lower' not allowed by security setting
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
*/
|
||||||
public function testNotAllowedModifier()
|
public function testNotAllowedModifier()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->allowed_modifiers = array('upper');
|
$this->smarty->security_policy->allowed_modifiers = array('upper');
|
||||||
try {
|
$this->smarty->fetch('string:{"hello"|upper}{"world"|lower}');
|
||||||
$this->smarty->fetch('eval:{"hello"|upper}{"world"|lower}');
|
}
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
$this->assertContains(htmlentities("modifier 'lower' not allowed by security setting"), $e->getMessage());
|
|
||||||
|
|
||||||
return;
|
/**
|
||||||
}
|
* test disabled modifier
|
||||||
$this->fail('Exception for not allowed tag has not been raised.');
|
* @expectedException SmartyException
|
||||||
}
|
* @expectedExceptionMessage modifier 'lower' disabled by security setting
|
||||||
|
* @runInSeparateProcess
|
||||||
/**
|
* @preserveGlobalState disabled
|
||||||
* test disabled modifier
|
*/
|
||||||
*/
|
|
||||||
public function testDisabledModifier()
|
public function testDisabledModifier()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->disabled_modifiers = array('lower');
|
$this->smarty->security_policy->disabled_modifiers = array('lower');
|
||||||
try {
|
$this->smarty->fetch('string:{"hello"|upper}{"world"|lower}');
|
||||||
$this->smarty->fetch('eval:{"hello"|upper}{"world"|lower}');
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
$this->assertContains(htmlentities("modifier 'lower' disabled by security setting"), $e->getMessage());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->fail('Exception for disabled tag has not been raised.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test Smarty::PHP_QUOTE
|
* test Smarty::PHP_QUOTE
|
||||||
*/
|
*/
|
||||||
public function testSmartyPhpQuote()
|
public function testSmartyPhpQuote()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->php_handling = Smarty::PHP_QUOTE;
|
$this->smarty->security_policy->php_handling = Smarty::PHP_QUOTE;
|
||||||
$this->assertEquals('<?php echo "hello world"; ?>', $this->smarty->fetch('eval:<?php echo "hello world"; ?>'));
|
$this->assertEquals('<?php echo "hello world"; ?>', $this->smarty->fetch('string:<?php echo "hello world"; ?>'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSmartyPhpQuoteAsp()
|
public function testSmartyPhpQuoteAsp()
|
||||||
@@ -228,16 +206,16 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
$this->markTestSkipped('asp tags disabled in php.ini');
|
$this->markTestSkipped('asp tags disabled in php.ini');
|
||||||
}
|
}
|
||||||
$this->smarty->security_policy->php_handling = Smarty::PHP_QUOTE;
|
$this->smarty->security_policy->php_handling = Smarty::PHP_QUOTE;
|
||||||
$this->assertEquals('<% echo "hello world"; %>', $this->smarty->fetch('eval:<% echo "hello world"; %>'));
|
$this->assertEquals('<% echo "hello world"; %>', $this->smarty->fetch('string:<% echo "hello world"; %>'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test Smarty::PHP_REMOVE
|
* test Smarty::PHP_REMOVE
|
||||||
*/
|
*/
|
||||||
public function testSmartyPhpRemove()
|
public function testSmartyPhpRemove()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->php_handling = Smarty::PHP_REMOVE;
|
$this->smarty->security_policy->php_handling = Smarty::PHP_REMOVE;
|
||||||
$this->assertEquals('', $this->smarty->fetch('eval:<?php echo "hello world"; ?>'));
|
$this->assertEquals('', $this->smarty->fetch('string:<?php echo "hello world"; ?>'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSmartyPhpRemoveAsp()
|
public function testSmartyPhpRemoveAsp()
|
||||||
@@ -247,16 +225,16 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
$this->markTestSkipped('asp tags disabled in php.ini');
|
$this->markTestSkipped('asp tags disabled in php.ini');
|
||||||
}
|
}
|
||||||
$this->smarty->security_policy->php_handling = Smarty::PHP_REMOVE;
|
$this->smarty->security_policy->php_handling = Smarty::PHP_REMOVE;
|
||||||
$this->assertEquals('', $this->smarty->fetch('eval:<% echo "hello world"; %>'));
|
$this->assertEquals('', $this->smarty->fetch('string:<% echo "hello world"; %>'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test Smarty::PHP_ALLOW
|
* test Smarty::PHP_ALLOW
|
||||||
*/
|
*/
|
||||||
public function testSmartyPhpAllow()
|
public function testSmartyPhpAllow()
|
||||||
{
|
{
|
||||||
$this->smartyBC->security_policy->php_handling = Smarty::PHP_ALLOW;
|
$this->smartyBC->security_policy->php_handling = Smarty::PHP_ALLOW;
|
||||||
$this->assertEquals('hello world', $this->smartyBC->fetch('eval:<?php echo "hello world"; ?>'));
|
$this->assertEquals('hello world', $this->smartyBC->fetch('string:<?php echo "hello world"; ?>'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSmartyPhpAllowAsp()
|
public function testSmartyPhpAllowAsp()
|
||||||
@@ -266,78 +244,71 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
$this->markTestSkipped('asp tags disabled in php.ini');
|
$this->markTestSkipped('asp tags disabled in php.ini');
|
||||||
}
|
}
|
||||||
$this->smartyBC->security_policy->php_handling = Smarty::PHP_ALLOW;
|
$this->smartyBC->security_policy->php_handling = Smarty::PHP_ALLOW;
|
||||||
$this->assertEquals('hello world', $this->smartyBC->fetch('eval:<% echo "hello world"; %>'));
|
$this->assertEquals('hello world', $this->smartyBC->fetch('string:<% echo "hello world"; %>'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test standard directory
|
* test standard directory
|
||||||
*/
|
*/
|
||||||
public function testStandardDirectory()
|
public function testStandardDirectory()
|
||||||
{
|
{
|
||||||
$content = $this->smarty->fetch('eval:{include file="helloworld.tpl"}');
|
$content = $this->smarty->fetch('string:{include file="helloworld.tpl"}');
|
||||||
$this->assertEquals("hello world", $content);
|
$this->assertEquals("hello world", $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test trusted directory
|
* test trusted directory
|
||||||
*/
|
*/
|
||||||
public function testTrustedDirectory()
|
public function testTrustedDirectory()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->secure_dir = array('.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR);
|
$this->smarty->security_policy->secure_dir = array('.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR);
|
||||||
$this->assertEquals("hello world", $this->smarty->fetch('eval:{include file="templates_2/hello.tpl"}'));
|
$this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test not trusted directory
|
* test not trusted directory
|
||||||
*/
|
*
|
||||||
|
* @expectedException SmartyException
|
||||||
|
* @expectedExceptionMessage not trusted file path
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
*/
|
||||||
public function testNotTrustedDirectory()
|
public function testNotTrustedDirectory()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->secure_dir = array(str_replace('\\', '/', dirname(__FILE__) . '/templates_3/'));
|
$this->smarty->security_policy->secure_dir = array(str_replace('\\', '/', dirname(__FILE__) . '/templates_3/'));
|
||||||
try {
|
$this->smarty->fetch('string:{include file="templates_2/hello.tpl"}');
|
||||||
$this->smarty->fetch('eval:{include file="templates_2/hello.tpl"}');
|
}
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
$this->assertContains(str_replace('\\', '/', dirname(__FILE__) . "/templates_2/hello.tpl' not allowed by security setting"), str_replace('\\', '/', $e->getMessage()));
|
|
||||||
|
|
||||||
return;
|
/**
|
||||||
}
|
* test disabled security for not trusted dir
|
||||||
$this->fail('Exception for not trusted directory has not been raised.');
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* test disabled security for not trusted dir
|
|
||||||
*/
|
|
||||||
public function testDisabledTrustedDirectory()
|
public function testDisabledTrustedDirectory()
|
||||||
{
|
{
|
||||||
$this->smarty->disableSecurity();
|
$this->smarty->disableSecurity();
|
||||||
$this->assertEquals("hello world", $this->smarty->fetch('eval:{include file="templates_2/hello.tpl"}'));
|
$this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test trusted static class
|
* test trusted static class
|
||||||
*/
|
*/
|
||||||
public function testTrustedStaticClass()
|
public function testTrustedStaticClass()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->static_classes = array('mysecuritystaticclass');
|
$this->smarty->security_policy->static_classes = array('mysecuritystaticclass');
|
||||||
$tpl = $this->smarty->createTemplate('eval:{mysecuritystaticclass::square(5)}');
|
$tpl = $this->smarty->createTemplate('string:{mysecuritystaticclass::square(5)}');
|
||||||
$this->assertEquals('25', $this->smarty->fetch($tpl));
|
$this->assertEquals('25', $this->smarty->fetch($tpl));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test not trusted PHP function
|
* test not trusted PHP function
|
||||||
*/
|
* @expectedException SmartyException
|
||||||
|
* @expectedExceptionMessage access to static class 'mysecuritystaticclass' not allowed by security setting
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
*/
|
||||||
public function testNotTrustedStaticClass()
|
public function testNotTrustedStaticClass()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->static_classes = array('null');
|
$this->smarty->security_policy->static_classes = array('null');
|
||||||
try {
|
$this->smarty->fetch('string:{mysecuritystaticclass::square(5)}');
|
||||||
$this->smarty->fetch('eval:{mysecuritystaticclass::square(5)}');
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
$this->assertContains(htmlentities("access to static class 'mysecuritystaticclass' not allowed by security setting"), $e->getMessage());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->fail('Exception for not trusted static class has not been raised.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testChangedTrustedDirectory()
|
public function testChangedTrustedDirectory()
|
||||||
@@ -345,43 +316,71 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
$this->smarty->security_policy->secure_dir = array(
|
$this->smarty->security_policy->secure_dir = array(
|
||||||
'.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR,
|
'.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR,
|
||||||
);
|
);
|
||||||
$this->assertEquals("hello world", $this->smarty->fetch('eval:{include file="templates_2/hello.tpl"}'));
|
$this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'));
|
||||||
|
|
||||||
$this->smarty->security_policy->secure_dir = array(
|
$this->smarty->security_policy->secure_dir = array(
|
||||||
'.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR,
|
'.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR,
|
||||||
'.' . DIRECTORY_SEPARATOR . 'templates_3' . DIRECTORY_SEPARATOR,
|
'.' . DIRECTORY_SEPARATOR . 'templates_3' . DIRECTORY_SEPARATOR,
|
||||||
);
|
);
|
||||||
$this->assertEquals("templates_3", $this->smarty->fetch('eval:{include file="templates_3/dirname.tpl"}'));
|
$this->assertEquals("templates_3", $this->smarty->fetch('string:{include file="templates_3/dirname.tpl"}'));
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* test template file exits
|
||||||
|
*
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
*/
|
||||||
|
public function testTemplateTrustedStream()
|
||||||
|
{
|
||||||
|
stream_wrapper_register("global", "ResourceStreamSecurity")
|
||||||
|
or die("Failed to register protocol");
|
||||||
|
$fp = fopen("global://mytest", "r+");
|
||||||
|
fwrite($fp, 'hello world {$foo}');
|
||||||
|
fclose($fp);
|
||||||
|
$this->smarty->security_policy->streams= array('global');
|
||||||
|
$tpl = $this->smarty->createTemplate('global:mytest');
|
||||||
|
$this->assertTrue($tpl->source->exists);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @expectedException SmartyException
|
||||||
|
* @expectedExceptionMessage stream 'global' not allowed by security setting
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
* test template file exits
|
||||||
|
*/
|
||||||
|
public function testTemplateNotTrustedStream()
|
||||||
|
{
|
||||||
|
stream_wrapper_register("global", "ResourceStreamSecurity")
|
||||||
|
or die("Failed to register protocol");
|
||||||
|
$fp = fopen("global://mytest", "r+");
|
||||||
|
fwrite($fp, 'hello world {$foo}');
|
||||||
|
fclose($fp);
|
||||||
|
$this->smarty->security_policy->streams= array('notrusted');
|
||||||
|
$tpl = $this->smarty->createTemplate('global:mytest');
|
||||||
|
$this->assertTrue($tpl->source->exists);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @runInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
*/
|
||||||
public function testTrustedUri()
|
public function testTrustedUri()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->trusted_uri = array(
|
$this->smarty->security_policy->trusted_uri = array(
|
||||||
'#^http://.+smarty\.net$#i'
|
'#https://www.smarty.net$#i'
|
||||||
);
|
);
|
||||||
|
$this->assertContains('<title>Preface | Smarty</title>', $this->smarty->fetch('string:{fetch file="https://www.smarty.net/docs/en/preface.tpl"}'));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
/**
|
||||||
$this->smarty->fetch('eval:{fetch file="http://www.smarty.net/foo.bar"}');
|
* @expectedException SmartyException
|
||||||
}
|
* @expectedExceptionMessage URI 'https://www.smarty.net/docs/en/preface.tpl' not allowed by security setting
|
||||||
catch (SmartyException $e) {
|
* @runInSeparateProcess
|
||||||
$this->assertNotContains(htmlentities("not allowed by security setting"), $e->getMessage());
|
* @preserveGlobalState disabled
|
||||||
}
|
*/
|
||||||
|
public function testNotTrustedUri()
|
||||||
try {
|
{
|
||||||
$this->smarty->fetch('eval:{fetch file="https://www.smarty.net/foo.bar"}');
|
$this->smarty->security_policy->trusted_uri = array();
|
||||||
$this->fail("Exception for unknown resource not thrown (protocol)");
|
$this->assertContains('<title>Preface | Smarty</title>', $this->smarty->fetch('string:{fetch file="https://www.smarty.net/docs/en/preface.tpl"}'));
|
||||||
}
|
|
||||||
catch (SmartyException $e) {
|
|
||||||
$this->assertContains(htmlentities("not allowed by security setting"), $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->smarty->fetch('eval:{fetch file="http://www.smarty.com/foo.bar"}');
|
|
||||||
$this->fail("Exception for unknown resource not thrown (domain)");
|
|
||||||
}
|
|
||||||
catch (SmartyException $e) {
|
|
||||||
$this->assertContains(htmlentities("not allowed by security setting"), $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,3 +398,74 @@ class Security extends Smarty_Security
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
class ResourceStreamSecurity
|
||||||
|
{
|
||||||
|
private $position;
|
||||||
|
private $varname;
|
||||||
|
|
||||||
|
public function stream_open($path, $mode, $options, &$opened_path)
|
||||||
|
{
|
||||||
|
$url = parse_url($path);
|
||||||
|
$this->varname = $url["host"];
|
||||||
|
$this->position = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_read($count)
|
||||||
|
{
|
||||||
|
$p = &$this->position;
|
||||||
|
$ret = substr($GLOBALS[$this->varname], $p, $count);
|
||||||
|
$p += strlen($ret);
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_write($data)
|
||||||
|
{
|
||||||
|
$v = &$GLOBALS[$this->varname];
|
||||||
|
$l = strlen($data);
|
||||||
|
$p = &$this->position;
|
||||||
|
$v = substr($v, 0, $p) . $data . substr($v, $p += $l);
|
||||||
|
|
||||||
|
return $l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_tell()
|
||||||
|
{
|
||||||
|
return $this->position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_eof()
|
||||||
|
{
|
||||||
|
if (!isset($GLOBALS[$this->varname])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->position >= strlen($GLOBALS[$this->varname]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_seek($offset, $whence)
|
||||||
|
{
|
||||||
|
$l = strlen($GLOBALS[$this->varname]);
|
||||||
|
$p = &$this->position;
|
||||||
|
switch ($whence) {
|
||||||
|
case SEEK_SET:
|
||||||
|
$newPos = $offset;
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
$newPos = $p + $offset;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
$newPos = $l + $offset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ret = ($newPos >= 0 && $newPos <= $l);
|
||||||
|
if ($ret) {
|
||||||
|
$p = $newPos;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user