Skip to content

Commit

Permalink
Merge branch 'master' into fixed_issue_554
Browse files Browse the repository at this point in the history
  • Loading branch information
nanasess authored Dec 23, 2024
2 parents 97a6322 + 664860e commit 9b654d4
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 44 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ jobs:
FORCE_COLOR: 1
run: yarn ${PATTERN} e2e-tests/${GROUP}

- name: Print error log
if: always()
continue-on-error: true
run: docker compose exec ec-cube tail -n 100 data/logs/error.log

- name: Upload evidence
if: failure()
uses: actions/upload-artifact@v4
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ jobs:
- name: Run to PHPUnit SessionFactory
run: docker compose exec -T ec-cube php data/vendor/bin/phpunit tests/class/SC_SessionFactoryTest.php

- name: Print error log
if: always()
continue-on-error: true
run: docker compose exec ec-cube tail -n 100 data/logs/error.log

- name: Upload logs
if: failure()
uses: actions/upload-artifact@v4
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"php": "^7.4 || ^8.0",
"ext-gd": "*",
"ext-mbstring": "*",
"ezyang/htmlpurifier": "^4.18",
"mobiledetect/mobiledetectlib": "^3.74",
"nanasess/mdb2": "^2.5",
"nanasess/php8-compat": "^1.0",
Expand Down
63 changes: 62 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion data/class/SC_View.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ public function __construct()

public function init()
{
// include_phpの利用のためSmartyBCを呼び出す、ホントはinclude_phpをなくしたいそうすれば、blank.tplもなくせる
$this->_smarty = new \Smarty\Smarty();
$this->_smarty->setLeftDelimiter('<!--{');
$this->_smarty->setRightDelimiter('}-->');
Expand Down Expand Up @@ -74,6 +73,7 @@ public function init()
$this->_smarty->registerPlugin('function', 'sfIsHTTPS', ['SC_Utils_Ex', 'sfIsHTTPS']);
$this->_smarty->registerPlugin('function', 'sfSetErrorStyle', ['SC_Utils_Ex', 'sfSetErrorStyle']);
$this->_smarty->registerPlugin('function', 'printXMLDeclaration', ['GC_Utils_Ex', 'printXMLDeclaration']);
$this->_smarty->muteUndefinedOrNullWarnings();
$this->_smarty->default_modifiers = ['script_escape'];

if (ADMIN_MODE == '1') {
Expand Down
9 changes: 8 additions & 1 deletion data/smarty_extends/modifier.script_escape.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
require_once __DIR__.'/../vendor/ezyang/htmlpurifier/library/HTMLPurifier.auto.php';
/**
* Scriptタグをエスケープする
*
Expand Down Expand Up @@ -50,5 +51,11 @@ function smarty_modifier_script_escape($value)
$value = preg_replace($pattern, $convert, $value);
}

return $value;
// 念のために HTMLPurifier でサニタイズ
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.SerializerPath', __DIR__.'/../cache');
$config->set('Attr.EnableID', true); // id 属性はサニタイズしない
$purify = new HTMLPurifier($config);

return $purify->purify($value ?? '');
}
80 changes: 39 additions & 41 deletions tests/class/modifier/Modifier_ScriptEscapeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,76 +2,74 @@

/**
* (省略。アノテーションを認識されるのに必要なようなので記述している。)
*
* PHP 8.1 でグローバル変数が消失する不具合を回避するため、下で `backupGlobals` を指定している。本質的には PHPUnit が PHP8 に対応していないのが原因と考えられる。
*
* @backupGlobals disabled
*/
class Modifier_ScriptEscapeTest extends PHPUnit_Framework_TestCase
{
public function scriptEscapeProvider()
{
$default_pattern = '/#script escaped#/';

return [
['<script type="text/javascript"></script>'],
['<svg onload="alert(1)">test</svg>'],
['<img onload="alert(1)">test</img>'],
['<body onload="alert(1)">test</body>'],
['<iframe></iframe>'],
['<object></object>'],
['<embed>'],
['\"onclick=\"alert(1)\"'],
['<p onclick="alert(1)">test</p>'],
['<p onsubmit="alert(1)">test</p>'],
['<p style="" onclick="alert(1)">test</p>'],
['<input type="button"onfocus="alert(1)">'],
['<input type="button" onblur="alert(1)">'],
['<input onfocus="alert(1)" type="button">'],
['<body onresize="alert(1)">'],
['<div onscroll="alert(1)">'],
['<div>javascript:test()</div>'],
['<input type="button" ondblclick="alert(1)">'],
['<input type="text" onchange="alert(1);">'],
['<input type="text" onselect="alert(1);">'],
['<form onsubmit="alert(1);">'],
['<input type="button" onkeydown="alert(1)">'],
['<input type="button" onkeypress="alert(1)">'],
['<input type="button" onkeyup="alert(1)">'],
['<input type=\"button\"\nonclick=\"alert(1)\">'],
['<div/onscroll="alert(1)">'],
['<script type="text/javascript"></script>', $default_pattern],
['<svg onload="alert(1)">test</svg>', $default_pattern],
['<img onload="alert(1)">test</img>', $default_pattern],
['<body onload="alert(1)">test</body>', $default_pattern],
['<iframe></iframe>', $default_pattern],
['<object></object>', $default_pattern],
['<embed>', $default_pattern],
['\"onclick=\"alert(1)\"', $default_pattern],
['<p onclick="alert(1)">test</p>', $default_pattern],
['<p onsubmit="alert(1)">test</p>', $default_pattern],
['<p style="" onclick="alert(1)">test</p>', $default_pattern],
['<input type="button"onfocus="alert(1)">', '//'], // HTMLPurifier によって完全に削除される
['<input type="button" onblur="alert(1)">', $default_pattern],
['<input onfocus="alert(1)" type="button">', $default_pattern],
['<body onresize="alert(1)">', $default_pattern],
['<div onscroll="alert(1)">', $default_pattern],
['<div>javascript:test()</div>', $default_pattern],
['<input type="button" ondblclick="alert(1)">', $default_pattern],
['<input type="text" onchange="alert(1);">', $default_pattern],
['<input type="text" onselect="alert(1);">', $default_pattern],
['<form onsubmit="alert(1);">', $default_pattern],
['<input type="button" onkeydown="alert(1)">', $default_pattern],
['<input type="button" onkeypress="alert(1)">', $default_pattern],
['<input type="button" onkeyup="alert(1)">', $default_pattern],
['<input type=\"button\"\nonclick=\"alert(1)\">', '//'], // HTMLPurifier によって完全に削除される
['<div/onscroll="alert(1)">', $default_pattern],
];
}

public function scriptNoEscapeProvider()
{
return [
['<p>test</p>'],
['<input type="button">'],
['<p>onclick</p>'],
['<div>test</div>'],
['<textarea>onclick="alert(1)";</textarea>'],
['<p>onclick="\ntest();"</p>'],
['<onclock'],
['<oncl\nick'],
['<p id="test" class="test">test</p>', '<p id="test" class="test">test</p>'],
['<input type="button">', ''], // 許可タグではないのでHTMLPurifier によって完全に削除される
['<p>onclick</p>', '<p>onclick</p>'],
['<div>test</div>', '<div>test</div>'],
['<textarea>onclick="alert(1)";</textarea>', 'onclick="alert(1)";'], // 許可タグではないのでHTMLPurifierによって textarea タグが削除される
['<p>onclick="\ntest();"</p>', '<p>onclick="\ntest();"</p>'],
['<onclock', ''], // 許可タグではないのでHTMLPurifier によって完全に削除される
['<oncl\nick', ''], // 許可タグではないのでHTMLPurifier によって完全に削除される
];
}

/**
* @dataProvider scriptEscapeProvider
*/
public function testメールテンプレートエスケープされる($value)
public function testメールテンプレートエスケープされる($value, $pattern)
{
$ret = smarty_modifier_script_escape($value);
$pattern = '/#script escaped#/';
$this->assertMatchesRegularExpression($pattern, $ret);
}

/**
* @dataProvider scriptNoEscapeProvider
*/
public function testメールテンプレートエスケープされない($value)
public function testメールテンプレートエスケープされない($value, $actual)
{
$ret = smarty_modifier_script_escape($value);
$pattern = '/#script escaped#/';
$this->assertDoesNotMatchRegularExpression($pattern, $ret);
$this->assertSame($ret, $actual);
}
}

0 comments on commit 9b654d4

Please sign in to comment.