mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
[ss-2015-021] Fix rewrite hash links XSS
This commit is contained in:
parent
e68eb7e45d
commit
97f21fddb3
@ -1,9 +1,28 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class SSViewerTest extends SapphireTest {
|
class SSViewerTest extends SapphireTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Backup of $_SERVER global
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $oldServer = array();
|
||||||
|
|
||||||
|
protected $extraDataObjects = array(
|
||||||
|
'SSViewerTest_Object',
|
||||||
|
);
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
Config::inst()->update('SSViewer', 'source_file_comments', false);
|
Config::inst()->update('SSViewer', 'source_file_comments', false);
|
||||||
|
Config::inst()->update('SSViewer_FromString', 'cache_template', false);
|
||||||
|
$this->oldServer = $_SERVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown() {
|
||||||
|
$_SERVER = $this->oldServer;
|
||||||
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1160,10 +1179,13 @@ after')
|
|||||||
$orig = Config::inst()->get('SSViewer', 'rewrite_hash_links');
|
$orig = Config::inst()->get('SSViewer', 'rewrite_hash_links');
|
||||||
Config::inst()->update('SSViewer', 'rewrite_hash_links', true);
|
Config::inst()->update('SSViewer', 'rewrite_hash_links', true);
|
||||||
|
|
||||||
$_SERVER['REQUEST_URI'] = 'http://path/to/file?foo"onclick="alert(\'xss\')""';
|
$_SERVER['HTTP_HOST'] = 'www.mysite.com';
|
||||||
|
$_SERVER['REQUEST_URI'] = '//file.com?foo"onclick="alert(\'xss\')""';
|
||||||
|
|
||||||
// Emulate SSViewer::process()
|
// Emulate SSViewer::process()
|
||||||
$base = Convert::raw2att($_SERVER['REQUEST_URI']);
|
// Note that leading double slashes have been rewritten to prevent these being mis-interepreted
|
||||||
|
// as protocol-less absolute urls
|
||||||
|
$base = Convert::raw2att('/file.com?foo"onclick="alert(\'xss\')""');
|
||||||
|
|
||||||
$tmplFile = TEMP_FOLDER . '/SSViewerTest_testRewriteHashlinks_' . sha1(rand()) . '.ss';
|
$tmplFile = TEMP_FOLDER . '/SSViewerTest_testRewriteHashlinks_' . sha1(rand()) . '.ss';
|
||||||
|
|
||||||
@ -1231,10 +1253,11 @@ after')
|
|||||||
$obj = new ViewableData();
|
$obj = new ViewableData();
|
||||||
$obj->InsertedLink = '<a class="inserted" href="#anchor">InsertedLink</a>';
|
$obj->InsertedLink = '<a class="inserted" href="#anchor">InsertedLink</a>';
|
||||||
$result = $tmpl->process($obj);
|
$result = $tmpl->process($obj);
|
||||||
$this->assertContains(
|
|
||||||
'<a class="inserted" href="<?php echo Convert::raw2att(',
|
$code = <<<'EOC'
|
||||||
$result
|
<a class="inserted" href="<?php echo Convert::raw2att(preg_replace("/^(\/)+/", "/", $_SERVER['REQUEST_URI'])); ?>#anchor">InsertedLink</a>
|
||||||
);
|
EOC;
|
||||||
|
$this->assertContains($code, $result);
|
||||||
// TODO Fix inline links in PHP mode
|
// TODO Fix inline links in PHP mode
|
||||||
// $this->assertContains(
|
// $this->assertContains(
|
||||||
// '<a class="inline" href="<?php echo str_replace(',
|
// '<a class="inline" href="<?php echo str_replace(',
|
||||||
|
@ -4681,11 +4681,15 @@ class SSTemplateParser extends Parser implements TemplateParser {
|
|||||||
|
|
||||||
// TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this
|
// TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this
|
||||||
// non-dynamically calculated
|
// non-dynamically calculated
|
||||||
|
$code = <<<'EOC'
|
||||||
|
(\Config::inst()->get('SSViewer', 'rewrite_hash_links')
|
||||||
|
? \Convert::raw2att( preg_replace("/^(\\/)+/", "/", $_SERVER['REQUEST_URI'] ) )
|
||||||
|
: "")
|
||||||
|
EOC;
|
||||||
|
// Because preg_replace replacement requires escaped slashes, addcslashes here
|
||||||
$text = preg_replace(
|
$text = preg_replace(
|
||||||
'/(<a[^>]+href *= *)"#/i',
|
'/(<a[^>]+href *= *)"#/i',
|
||||||
'\\1"\' . (Config::inst()->get(\'SSViewer\', \'rewrite_hash_links\') ?' .
|
'\\1"\' . ' . addcslashes($code, '\\') . ' . \'#',
|
||||||
' Convert::raw2att( $_SERVER[\'REQUEST_URI\'] ) : "") .
|
|
||||||
\'#',
|
|
||||||
$text
|
$text
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1135,11 +1135,15 @@ class SSTemplateParser extends Parser implements TemplateParser {
|
|||||||
|
|
||||||
// TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this
|
// TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this
|
||||||
// non-dynamically calculated
|
// non-dynamically calculated
|
||||||
|
$code = <<<'EOC'
|
||||||
|
(\Config::inst()->get('SSViewer', 'rewrite_hash_links')
|
||||||
|
? \Convert::raw2att( preg_replace("/^(\\/)+/", "/", $_SERVER['REQUEST_URI'] ) )
|
||||||
|
: "")
|
||||||
|
EOC;
|
||||||
|
// Because preg_replace replacement requires escaped slashes, addcslashes here
|
||||||
$text = preg_replace(
|
$text = preg_replace(
|
||||||
'/(<a[^>]+href *= *)"#/i',
|
'/(<a[^>]+href *= *)"#/i',
|
||||||
'\\1"\' . (Config::inst()->get(\'SSViewer\', \'rewrite_hash_links\') ?' .
|
'\\1"\' . ' . addcslashes($code, '\\') . ' . \'#',
|
||||||
' Convert::raw2att( $_SERVER[\'REQUEST_URI\'] ) : "") .
|
|
||||||
\'#',
|
|
||||||
$text
|
$text
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1111,9 +1111,9 @@ class SSViewer implements Flushable {
|
|||||||
if($this->rewriteHashlinks && $rewrite) {
|
if($this->rewriteHashlinks && $rewrite) {
|
||||||
if(strpos($output, '<base') !== false) {
|
if(strpos($output, '<base') !== false) {
|
||||||
if($rewrite === 'php') {
|
if($rewrite === 'php') {
|
||||||
$thisURLRelativeToBase = "<?php echo Convert::raw2att(\$_SERVER['REQUEST_URI']); ?>";
|
$thisURLRelativeToBase = "<?php echo Convert::raw2att(preg_replace(\"/^(\\\\/)+/\", \"/\", \$_SERVER['REQUEST_URI'])); ?>";
|
||||||
} else {
|
} else {
|
||||||
$thisURLRelativeToBase = Convert::raw2att($_SERVER['REQUEST_URI']);
|
$thisURLRelativeToBase = Convert::raw2att(preg_replace("/^(\\/)+/", "/", $_SERVER['REQUEST_URI']));
|
||||||
}
|
}
|
||||||
|
|
||||||
$output = preg_replace('/(<a[^>]+href *= *)"#/i', '\\1"' . $thisURLRelativeToBase . '#', $output);
|
$output = preg_replace('/(<a[^>]+href *= *)"#/i', '\\1"' . $thisURLRelativeToBase . '#', $output);
|
||||||
|
Loading…
Reference in New Issue
Block a user