EC-CUBE 2系におけるクロスサイトスクリプティングの脆弱性(JVN#04785663)

更新履歴
2023/02/28 11:00
謝辞を追加
2023/02/21 14:55
【重要】2.17系の適用手順での注意事項を追記いたしました
本脆弱性とは別に、今回の修正箇所と同じ画面に致命的な既存バグが存在していることが判明したため、2.17系での対応時の注意事項を追記しました。
2023/02/21 14:55
【重要】修正ファイル(2.13用、2.17用の2点)の内容に不具合がありましたので、ファイルを更新いたしました。
公開されていた時間:2023/02/14 17:00 〜 2023/02/21 14:55 上記時間帯にファイルの適応を行った方は、再度のご確認と修正対応をお願いいたします。
2023/02/20 16:45
【重要】修正ファイルに不具合を確認
修正ファイルにより脆弱性は解消されますが、一部不具合があり現在新しい修正ファイルを準備中です。
2023/02/15 16:30
2.13系の修正方法を追加 (※2.17系の修正方法には変更ございません)
2023/02/14 17:00
初版公開

EC-CUBEにおけるクロスサイトスクリプティングの脆弱性

EC-CUBE 2系におけるクロスサイトスクリプティングの脆弱性(危険度: 低)があることが判明いたしました。

脆弱性そのものは、修正の反映によりすぐに解決するものです。
以下のいずれかの方法により、ご対応をお願いいたします。

皆様にはお手数おかけし誠に申し訳ございません。
本脆弱性における被害報告は現時点でございませんが、できるだけ速やかにご対応をお願いいたします。

脆弱性の概要

EC-CUBEにおけるクロスサイトスクリプティングの脆弱性

危険度:

不具合が存在するEC-CUBEのバージョン:

詳細:

該当バージョンのEC-CUBEにはXSSの脆弱性が存在します。攻撃者は当該脆弱性を悪用して、被害者のブラウザ上で任意のスクリプトを実行させる可能性があります。


JVNからの公表内容 (2022/02/28公開)

JVN#04785663: EC-CUBE における複数のクロスサイトスクリプティングの脆弱性

2.17系での対応時の注意事項

2.17系をご利用の場合、以下の注意事項をご確認お願いいたします。

2.17系では本脆弱性とは別に、ファイル管理の機能にて、ファイルの削除時にuser_dataディレクトリ配下が削除される不具合が存在します。
いずれかのファイルを削除後、リロードを行うと不具合が再現いたします。
https://github.com/EC-CUBE/ec-cube2/issues/682
修正適用後に動作確認を行う際には、くれぐれもご注意をお願いいたします。

修正方法1: 修正ファイルを利用する場合

2.17系の更新をされる方は、2.17系での対応時の注意事項をご一読下さい。

開発環境がある場合は、まず開発環境でお試しください。
以下の手順に従って、修正ファイルの反映をお願いいたします。

  1. 修正ファイルのダウンロード

    ご利用中のEC-CUBEのバージョンに該当する修正ファイルをダウンロードしてください。
    ※EC-CUBEのバージョンはこちらの手順でご確認ください。
    ※修正ファイルは各バージョンの最新版に対して作成しています。旧バージョンをご利用の場合は、「修正方法2」のご対応をお願いします。

    ダウンロードし、解凍していただきますと、以下の修正ファイルがあります。必ず該当するバージョンのファイルをご利用ください。

    • data/Smarty/templates/admin/contents/file_manager.tpl
    • data/class/pages/admin/contents/LC_Page_Admin_Contents_FileManager.php
  2. EC-CUBEファイルのバックアップ

    あらかじめEC-CUBEファイル全体のバックアップを行ってください。

  3. 修正ファイルの反映

    以下のファイルを上書き更新してください。

    上書きするファイル

    • data/Smarty/templates/admin/contents/file_manager.tpl
    • data/class/pages/admin/contents/LC_Page_Admin_Contents_FileManager.php
    ※EC-CUBE本体のカスタマイズをしている場合、修正箇所の差分をご確認のうえ反映をお願いします。
    ※開発環境がある場合は、開発環境での反映・動作確認を行った後に、本番環境への反映をおすすめします。

  4. キャッシュの削除

    キャッシュは自動で更新されますが、念の為EC-CUBE のキャッシュの削除をしておくと安全です。以下のディレクトリ配下のキャッシュファイルを削除をお願い致します。

    • data/Smarty/templates_c/admin/*
    ※ディレクトリごと削除せず、配下のファイルを削除するようにしてください。
  5. 動作確認

    管理画面にログインし、基本操作が正常に行えることをご確認ください。

修正方法2-1: 修正差分を確認して適宜反映する場合(2.13系)

以下のコード差分情報を参照して頂き、必要な箇所に修正を反映してください。

本修正方法はEC-CUBE 2.13.5のバージョンを例として提示しております。
過去バージョンをご利用の場合は、下記修正対象ファイルの修正差分を参考にご対応お願いいたします。

修正差分

data/Smarty/templates/admin/contents/file_manager.tpl CHANGED
@@ -31,11 +31,58 @@
31
31
  var total = bread_crumbs.length;
32
32
  for (var i in bread_crumbs) {
33
33
  file_path += bread_crumbs[i] + '/';
34
- $('<a href="javascript:;" onclick="eccube.fileManager.openFolder(\'' + file_path + '\'); return false;" />')
34
+ $('<a href="javascript:;" />')
35
+ .attr('data-filepath', file_path)
35
36
  .text(bread_crumbs[i])
37
+ .addClass('open')
36
38
  .appendTo($node);
37
39
  if (i < total - 1) $node.append($delimiter);
38
40
  }
41
+ $('a.open[data-filepath]').on('click', function() {
42
+ var filepath = $(this).data('filepath');
43
+ eccube.fileManager.openFolder(filepath);
44
+
45
+ return false;
46
+ });
47
+ $('a.cd[data-filepath]').on('click', function() {
48
+ var filepath = $(this).data('filepath');
49
+ var id = $(this).data('id');
50
+ eccube.setValue('tree_select_file', filepath, 'form1');
51
+ eccube.fileManager.selectFile(id, '#808080');
52
+ eccube.setModeAndSubmit('move','','');
53
+
54
+ return false;
55
+ });
56
+ $('a.view[data-filepath]').on('click', function() {
57
+ var filepath = $(this).data('filepath');
58
+ var id = $(this).data('id');
59
+ eccube.setValue('select_file', filepath, 'form1');
60
+ eccube.fileManager.selectFile(id, '#808080');
61
+ filepath = filepath.replace(/<!--{$smarty.const.USER_REALDIR|preg_quote:"/"}-->/, '');
62
+ eccube.openWindow('./file_view.php?file='+ filepath, 'user_data', '600', '400');
63
+
64
+ return false;
65
+ });
66
+ $('a.download[data-filepath]').on('click', function () {
67
+ var filepath = $(this).data('filepath');
68
+ var id = $(this).data('id');
69
+ eccube.setValue('select_file', filepath, 'form1');
70
+ eccube.fileManager.selectFile(id, '#808080');
71
+ eccube.fileManager.setTreeStatus('tree_status');
72
+ eccube.setModeAndSubmit('download','','');
73
+
74
+ return false;
75
+ });
76
+ $('a.delete[data-filepath]').on('click', function () {
77
+ var filepath = $(this).data('filepath');
78
+ var id = $(this).data('id');
79
+ eccube.setValue('select_file', filepath, 'form1');
80
+ eccube.fileManager.selectFile(id, '#808080');
81
+ eccube.fileManager.setTreeStatus('tree_status');
82
+ eccube.setModeAndSubmit('delete','','');
83
+
84
+ return false;
85
+ });
39
86
  });
40
87
 
41
88
  eccube.fileManager.IMG_FOLDER_CLOSE = "<!--{$TPL_URLPATH}-->img/contents/folder_close.gif"; // フォルダクローズ時画像
@@ -84,7 +131,7 @@
84
131
  <th class="delete">削除</th>
85
132
  </tr>
86
133
  <!--{if !$tpl_is_top_dir}-->
87
- <tr id="parent_dir" onclick="eccube.setValue('select_file', '<!--{$tpl_parent_dir|h}-->', 'form1'); eccube.fileManager.selectFile('parent_dir', '#808080');" onDblClick="eccube.fileManager.setTreeStatus('tree_status');eccube.fileManager.toggleTreeMenu('tree'+cnt, 'rank_img'+cnt, arrTree[cnt][2]);eccube.fileManager.doubleClick(arrTree, '<!--{$tpl_parent_dir|h}-->', true, '<!--{$tpl_now_dir|h}-->', true)" style="">
134
+ <tr id="parent_dir">
88
135
  <td>
89
136
  <img src="<!--{$TPL_URLPATH}-->img/contents/folder_parent.gif" alt="フォルダ">&nbsp;..
90
137
  </td>
@@ -98,7 +145,7 @@
98
145
  <!--{section name=cnt loop=$arrFileList}-->
99
146
  <!--{assign var="id" value="select_file`$smarty.section.cnt.index`"}-->
100
147
  <tr id="<!--{$id}-->" style="">
101
- <td class="file-name" onDblClick="eccube.fileManager.setTreeStatus('tree_status');eccube.fileManager.doubleClick(arrTree, '<!--{$arrFileList[cnt].file_path|h}-->', <!--{if $arrFileList[cnt].is_dir|h}-->true<!--{else}-->false<!--{/if}-->, '<!--{$tpl_now_dir|h}-->', false)">
148
+ <td class="file-name">
102
149
  <!--{if $arrFileList[cnt].is_dir}-->
103
150
  <img src="<!--{$TPL_URLPATH}-->img/contents/folder_close.gif" alt="フォルダ" />
104
151
  <!--{else}-->
@@ -114,11 +161,11 @@
114
161
  </td>
115
162
  <!--{if $arrFileList[cnt].is_dir}-->
116
163
  <td class="center">
117
- <a href="javascript:;" onclick="eccube.setValue('tree_select_file', '<!--{$arrFileList[cnt].file_path}-->', 'form1'); eccube.fileManager.selectFile('<!--{$id}-->', '#808080');eccube.setModeAndSubmit('move','',''); return false;">表示</a>
164
+ <a href="javascript:;" class="cd" data-filepath="<!--{$arrFileList[cnt].file_path|h}-->" data-id="<!--{$id|h}-->">表示</a>
118
165
  </td>
119
166
  <!--{else}-->
120
167
  <td class="center">
121
- <a href="javascript:;" onclick="eccube.setValue('select_file', '<!--{$arrFileList[cnt].file_path|h}-->', 'form1');eccube.fileManager.selectFile('<!--{$id}-->', '#808080');eccube.setModeAndSubmit('view','',''); return false;">表示</a>
168
+ <a href="javascript:;" class="view" data-filepath="<!--{$arrFileList[cnt].file_path|h}-->" data-id="<!--{$id|h}-->">表示</a>
122
169
  </td>
123
170
  <!--{/if}-->
124
171
  <!--{if $arrFileList[cnt].is_dir}-->
@@ -126,11 +173,11 @@
126
173
  <td class="center">-</td>
127
174
  <!--{else}-->
128
175
  <td class="center">
129
- <a href="javascript:;" onclick="eccube.setValue('select_file', '<!--{$arrFileList[cnt].file_path|h}-->', 'form1');eccube.fileManager.selectFile('<!--{$id}-->', '#808080');eccube.fileManager.setTreeStatus('tree_status');eccube.setModeAndSubmit('download','',''); return false;">ダウンロード</a>
176
+ <a href="javascript:;" class="download" data-filepath="<!--{$arrFileList[cnt].file_path|h}-->" data-id="<!--{$id|h}-->">ダウンロード</a>
130
177
  </td>
131
178
  <!--{/if}-->
132
179
  <td class="center">
133
- <a href="javascript:;" onclick="eccube.setValue('select_file', '<!--{$arrFileList[cnt].file_path|h}-->', 'form1');eccube.fileManager.selectFile('<!--{$id}-->', '#808080');eccube.fileManager.setTreeStatus('tree_status');eccube.setModeAndSubmit('delete','',''); return false;">削除</a>
180
+ <a href="javascript:;" class="delete" data-filepath="<!--{$arrFileList[cnt].file_path|h}-->" data-id="<!--{$id|h}-->">削除</a>
134
181
  </td>
135
182
  </tr>
136
183
  <!--{/section}-->
data/class/pages/admin/contents/LC_Page_Admin_Contents_FileManager.php CHANGED
@@ -95,24 +95,6 @@ class LC_Page_Admin_Contents_FileManager extends LC_Page_Admin_Ex
95
95
  }
96
96
  break;
97
97
 
98
- // ファイル表示
99
- case 'view':
100
- $objFormParam = new SC_FormParam_Ex();
101
- $this->lfInitParamModeView($objFormParam);
102
- $objFormParam->setParam($this->createSetParam($_POST));
103
- $objFormParam->convParam();
104
-
105
- $this->arrErr = $objFormParam->checkError();
106
- if (SC_Utils_Ex::isBlank($this->arrErr)) {
107
- if ($this->tryView($objFormParam)) {
108
- $pattern = '/' . preg_quote($objFormParam->getValue('top_dir'), '/') . '/';
109
- $file_url = htmlspecialchars(preg_replace($pattern, '', $objFormParam->getValue('select_file')));
110
- $tpl_onload = "eccube.openWindow('./file_view.php?file=". $file_url ."', 'user_data', '600', '400');";
111
- $this->setTplOnLoad($tpl_onload);
112
- }
113
- }
114
- break;
115
-
116
98
  // ファイルダウンロード
117
99
  case 'download':
118
100
  $objFormParam = new SC_FormParam_Ex();

修正方法2-2: 修正差分を確認して適宜反映する場合(2.17系)

2.17系の更新をされる方は、2.17系での対応時の注意事項をご一読下さい。

以下のコード差分情報を参照して頂き、必要な箇所に修正を反映してください。

本修正方法はEC-CUBE 2.17.2のバージョンを例として提示しております。
過去バージョンをご利用の場合は、下記修正対象ファイルの修正差分を参考にご対応お願いいたします。

修正差分

data/Smarty/templates/admin/contents/file_manager.tpl CHANGED
@@ -31,11 +31,58 @@
31
31
  var total = bread_crumbs.length;
32
32
  for (var i in bread_crumbs) {
33
33
  file_path += bread_crumbs[i] + '/';
34
- $('<a href="javascript:;" onclick="eccube.fileManager.openFolder(\'' + file_path + '\'); return false;" />')
34
+ $('<a href="javascript:;" />')
35
+ .attr('data-filepath', file_path)
35
36
  .text(bread_crumbs[i])
37
+ .addClass('open')
36
38
  .appendTo($node);
37
39
  if (i < total - 1) $node.append($delimiter);
38
40
  }
41
+ $('a.open[data-filepath]').on('click', function() {
42
+ var filepath = $(this).data('filepath');
43
+ eccube.fileManager.openFolder(filepath);
44
+
45
+ return false;
46
+ });
47
+ $('a.cd[data-filepath]').on('click', function() {
48
+ var filepath = $(this).data('filepath');
49
+ var id = $(this).data('id');
50
+ eccube.setValue('tree_select_file', filepath, 'form1');
51
+ eccube.fileManager.selectFile(id, '#808080');
52
+ eccube.setModeAndSubmit('move','','');
53
+
54
+ return false;
55
+ });
56
+ $('a.view[data-filepath]').on('click', function() {
57
+ var filepath = $(this).data('filepath');
58
+ var id = $(this).data('id');
59
+ eccube.setValue('select_file', filepath, 'form1');
60
+ eccube.fileManager.selectFile(id, '#808080');
61
+ filepath = filepath.replace(/<!--{$smarty.const.USER_DIR|preg_quote:"/"}-->/, '');
62
+ eccube.openWindow('./file_view.php?file='+ filepath, 'user_data', '600', '400');
63
+
64
+ return false;
65
+ });
66
+ $('a.download[data-filepath]').on('click', function () {
67
+ var filepath = $(this).data('filepath');
68
+ var id = $(this).data('id');
69
+ eccube.setValue('select_file', filepath, 'form1');
70
+ eccube.fileManager.selectFile(id, '#808080');
71
+ eccube.fileManager.setTreeStatus('tree_status');
72
+ eccube.setModeAndSubmit('download','','');
73
+
74
+ return false;
75
+ });
76
+ $('a.delete[data-filepath]').on('click', function () {
77
+ var filepath = $(this).data('filepath');
78
+ var id = $(this).data('id');
79
+ eccube.setValue('select_file', filepath, 'form1');
80
+ eccube.fileManager.selectFile(id, '#808080');
81
+ eccube.fileManager.setTreeStatus('tree_status');
82
+ eccube.setModeAndSubmit('delete','','');
83
+
84
+ return false;
85
+ });
39
86
  });
40
87
 
41
88
  eccube.fileManager.IMG_FOLDER_CLOSE = "<!--{$TPL_URLPATH}-->img/contents/folder_close.gif"; // フォルダクローズ時画像
@@ -84,7 +131,7 @@
84
131
  <th class="delete">削除</th>
85
132
  </tr>
86
133
  <!--{if !$tpl_is_top_dir}-->
87
- <tr id="parent_dir" onclick="eccube.setValue('select_file', '<!--{$tpl_parent_dir|h}-->', 'form1'); eccube.fileManager.selectFile('parent_dir', '#808080');" onDblClick="eccube.fileManager.setTreeStatus('tree_status');eccube.fileManager.toggleTreeMenu('tree'+cnt, 'rank_img'+cnt, arrTree[cnt][2]);eccube.fileManager.doubleClick(arrTree, '<!--{$tpl_parent_dir|h}-->', true, '<!--{$tpl_now_dir|h}-->', true)" style="">
134
+ <tr id="parent_dir">
88
135
  <td>
89
136
  <img src="<!--{$TPL_URLPATH}-->img/contents/folder_parent.gif" alt="フォルダ">&nbsp;..
90
137
  </td>
@@ -98,7 +145,7 @@
98
145
  <!--{section name=cnt loop=$arrFileList}-->
99
146
  <!--{assign var="id" value="select_file`$smarty.section.cnt.index`"}-->
100
147
  <tr id="<!--{$id}-->" style="">
101
- <td class="file-name" onDblClick="eccube.fileManager.setTreeStatus('tree_status');eccube.fileManager.doubleClick(arrTree, '<!--{$arrFileList[cnt].file_path|h}-->', <!--{if $arrFileList[cnt].is_dir|h}-->true<!--{else}-->false<!--{/if}-->, '<!--{$tpl_now_dir|h}-->', false)">
148
+ <td class="file-name">
102
149
  <!--{if $arrFileList[cnt].is_dir}-->
103
150
  <img src="<!--{$TPL_URLPATH}-->img/contents/folder_close.gif" alt="フォルダ" />
104
151
  <!--{else}-->
@@ -114,11 +161,11 @@
114
161
  </td>
115
162
  <!--{if $arrFileList[cnt].is_dir}-->
116
163
  <td class="center">
117
- <a href="javascript:;" onclick="eccube.setValue('tree_select_file', '<!--{$arrFileList[cnt].file_path}-->', 'form1'); eccube.fileManager.selectFile('<!--{$id}-->', '#808080');eccube.setModeAndSubmit('move','',''); return false;">表示</a>
164
+ <a href="javascript:;" class="cd" data-filepath="<!--{$arrFileList[cnt].file_path|h}-->" data-id="<!--{$id|h}-->">表示</a>
118
165
  </td>
119
166
  <!--{else}-->
120
167
  <td class="center">
121
- <a href="javascript:;" onclick="eccube.setValue('select_file', '<!--{$arrFileList[cnt].file_path|h}-->', 'form1');eccube.fileManager.selectFile('<!--{$id}-->', '#808080');eccube.setModeAndSubmit('view','',''); return false;">表示</a>
168
+ <a href="javascript:;" class="view" data-filepath="<!--{$arrFileList[cnt].file_path|h}-->" data-id="<!--{$id|h}-->">表示</a>
122
169
  </td>
123
170
  <!--{/if}-->
124
171
  <!--{if $arrFileList[cnt].is_dir}-->
@@ -126,11 +173,11 @@
126
173
  <td class="center">-</td>
127
174
  <!--{else}-->
128
175
  <td class="center">
129
- <a href="javascript:;" onclick="eccube.setValue('select_file', '<!--{$arrFileList[cnt].file_path|h}-->', 'form1');eccube.fileManager.selectFile('<!--{$id}-->', '#808080');eccube.fileManager.setTreeStatus('tree_status');eccube.setModeAndSubmit('download','',''); return false;">ダウンロード</a>
176
+ <a href="javascript:;" class="download" data-filepath="<!--{$arrFileList[cnt].file_path|h}-->" data-id="<!--{$id|h}-->">ダウンロード</a>
130
177
  </td>
131
178
  <!--{/if}-->
132
179
  <td class="center">
133
- <a href="javascript:;" onclick="eccube.setValue('select_file', '<!--{$arrFileList[cnt].file_path|h}-->', 'form1');eccube.fileManager.selectFile('<!--{$id}-->', '#808080');eccube.fileManager.setTreeStatus('tree_status');eccube.setModeAndSubmit('delete','',''); return false;">削除</a>
180
+ <a href="javascript:;" class="delete" data-filepath="<!--{$arrFileList[cnt].file_path|h}-->" data-id="<!--{$id|h}-->">削除</a>
134
181
  </td>
135
182
  </tr>
136
183
  <!--{/section}-->
data/class/pages/admin/contents/LC_Page_Admin_Contents_FileManager.php CHANGED
@@ -100,24 +100,6 @@ class LC_Page_Admin_Contents_FileManager extends LC_Page_Admin_Ex
100
100
  }
101
101
  break;
102
102
 
103
- // ファイル表示
104
- case 'view':
105
- $objFormParam = new SC_FormParam_Ex();
106
- $this->lfInitParamModeView($objFormParam);
107
- $objFormParam->setParam($this->createSetParam($_POST));
108
- $objFormParam->convParam();
109
-
110
- $this->arrErr = $objFormParam->checkError();
111
- if (SC_Utils_Ex::isBlank($this->arrErr)) {
112
- if ($this->tryView($objFormParam)) {
113
- $pattern = '/' . preg_quote($objFormParam->getValue('top_dir'), '/') . '/';
114
- $file_url = htmlspecialchars(preg_replace($pattern, '', $objFormParam->getValue('select_file')));
115
- $tpl_onload = "eccube.openWindow('./file_view.php?file=". $file_url ."', 'user_data', '600', '400');";
116
- $this->setTplOnLoad($tpl_onload);
117
- }
118
- }
119
- break;
120
-
121
103
  // ファイルダウンロード
122
104
  case 'download':
123
105
  $objFormParam = new SC_FormParam_Ex();

問い合わせ先

本脆弱性に関するお問合せ:

EC-CUBE 運営チーム
MAIL: support@ec-cube.net

謝辞

本脆弱性は、

コンテンツ管理におけるクロスサイトスクリプティング CVE-2023-22438

よりご報告いただきました。
この場をお借りして、厚く御礼申し上げます。