EC-CUBE 4系におけるプラグインインストール時の入力値チェックの不備(JVN#48324254)

更新履歴
2024/07/30 14:00
JVNからの公表内容情報へのリンクを追加
2024/07/17 14:00
初版公開

EC-CUBE 4系におけるプラグインインストール時の入力値チェックの不備

EC-CUBE 4系におけるプラグインインストール時の入力値チェック不備の脆弱性(緊急度: 低)があることが判明いたしました。

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

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

脆弱性の概要

EC-CUBE 4系におけるプラグインインストール時の入力値チェック不備の脆弱性

危険度:

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

詳細:

プラグインインストール時の入力値のチェックに不備があるため、任意のPHPパッケージをダウンロード可能です。


JVNからの公表内容 (2024/07/30公開)

JVN#48324254: EC-CUBE 4系におけるプラグインインストール時の入力値チェックの不備

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

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

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

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

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

    4.0.6-p4

    • src/Eccube/Controller/Admin/Store/OwnerStoreController.php

    4.1.2-p3

    • src/Eccube/Controller/Admin/Store/OwnerStoreController.php

    4.2.3

    • src/Eccube/Controller/Admin/Store/OwnerStoreController.php
  2. EC-CUBEファイルのバックアップ

    あらかじめEC-CUBEファイル全体のバックアップを行ってください。
    ※作業中はメンテナンスモードに切り替えることをおすすめします。

  3. 修正ファイルの反映

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

    上書きするファイル

    4.0.6-p4

    • src/Eccube/Controller/Admin/Store/OwnerStoreController.php

    4.1.2-p3

    • src/Eccube/Controller/Admin/Store/OwnerStoreController.php

    4.2.3

    • src/Eccube/Controller/Admin/Store/OwnerStoreController.php
    ※デザインテンプレートの適用や、EC-CUBE本体のカスタマイズをしている場合、修正箇所の差分をご確認のうえ反映をお願いします。
    ※開発環境がある場合は、開発環境での反映・動作確認を行った後に、本番環境への反映をおすすめします。

  4. キャッシュの削除

    EC-CUBE のキャッシュの削除が必要です。
    EC-CUBE の管理画面にログインいただき、コンテンツ管理 -> キャッシュ管理 のページからキャッシュの削除をお願いいたします。

  5. 動作確認

    フロント画面と管理画面(ログインが必要)それぞれにおいて、基本操作が正常に行えることをご確認ください。
    ※メンテナンスモードにされていた場合は解除をお願いします。

修正方法2-1: 修正差分を確認して適用する場合(4.0系)

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

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

修正差分

src/Eccube/Controller/Admin/Store/OwnerStoreController.php CHANGED
@@ -32,6 +32,8 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
32
32
  use Symfony\Component\HttpFoundation\Request;
33
33
  use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
34
34
  use Symfony\Component\Routing\Annotation\Route;
35
+ use Symfony\Component\Validator\Constraints as Assert;
36
+ use Symfony\Component\Validator\Validator\ValidatorInterface;
35
37
 
36
38
  /**
37
39
  * @Route("/%eccube_admin_route%/store/plugin/api")
@@ -63,6 +65,11 @@ class OwnerStoreController extends AbstractController
63
65
  */
64
66
  protected $pluginApiService;
65
67
 
68
+ /**
69
+ * @var ValidatorInterface
70
+ */
71
+ protected $validator;
72
+
66
73
  private static $vendorName = 'ec-cube';
67
74
 
68
75
  /** @var BaseInfo */
@@ -81,6 +88,7 @@ class OwnerStoreController extends AbstractController
81
88
  * @param PluginApiService $pluginApiService
82
89
  * @param BaseInfoRepository $baseInfoRepository
83
90
  * @param CacheUtil $cacheUtil
91
+ * @param ValidatorInterface $validatorInterface
84
92
  *
85
93
  * @throws \Doctrine\ORM\NoResultException
86
94
  * @throws \Doctrine\ORM\NonUniqueResultException
@@ -92,7 +100,8 @@ class OwnerStoreController extends AbstractController
92
100
  SystemService $systemService,
93
101
  PluginApiService $pluginApiService,
94
102
  BaseInfoRepository $baseInfoRepository,
95
- CacheUtil $cacheUtil
103
+ CacheUtil $cacheUtil,
104
+ ValidatorInterface $validatorInterface
96
105
  ) {
97
106
  $this->pluginRepository = $pluginRepository;
98
107
  $this->pluginService = $pluginService;
@@ -100,6 +109,7 @@ class OwnerStoreController extends AbstractController
100
109
  $this->pluginApiService = $pluginApiService;
101
110
  $this->BaseInfo = $baseInfoRepository->get();
102
111
  $this->cacheUtil = $cacheUtil;
112
+ $this->validator = $validatorInterface;
103
113
 
104
114
  // TODO: Check the flow of the composer service below
105
115
  $this->composerService = $composerService;
@@ -266,14 +276,32 @@ class OwnerStoreController extends AbstractController
266
276
 
267
277
  $pluginCode = $request->get('pluginCode');
268
278
 
269
- $log = null;
270
- try {
271
- $log = $this->composerService->execRequire('ec-cube/'.$pluginCode);
272
-
273
- return $this->json(['success' => true, 'log' => $log]);
274
- } catch (\Exception $e) {
275
- $log = $e->getMessage();
276
- log_error($e);
279
+ $errors = $this->validator->validate(
280
+ $pluginCode,
281
+ [
282
+ new Assert\NotBlank(),
283
+ new Assert\Regex(
284
+ [
285
+ 'pattern' => '/^[a-zA-Z0-9_]+$/',
286
+ ]
287
+ ),
288
+ ]
289
+ );
290
+
291
+ if ($errors->count() != 0) {
292
+ $log = [];
293
+ foreach ($errors as $error) {
294
+ $log[] = $error->getMessage();
295
+ }
296
+ } else {
297
+ try {
298
+ $log = $this->composerService->execRequire('ec-cube/'.$pluginCode);
299
+
300
+ return $this->json(['success' => true, 'log' => $log]);
301
+ } catch (\Exception $e) {
302
+ $log = $e->getMessage();
303
+ log_error($e);
304
+ }
277
305
  }
278
306
 
279
307
  return $this->json(['success' => false, 'log' => $log], 500);
@@ -350,14 +378,53 @@ class OwnerStoreController extends AbstractController
350
378
  $pluginCode = $request->get('pluginCode');
351
379
  $version = $request->get('version');
352
380
 
353
- $log = null;
354
- try {
355
- $log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);
381
+ $log = [];
382
+
383
+ $errors = $this->validator->validate(
384
+ $pluginCode,
385
+ [
386
+ new Assert\NotBlank(),
387
+ new Assert\Regex(
388
+ [
389
+ 'pattern' => '/^[a-zA-Z0-9_]+$/',
390
+ ]
391
+ ),
392
+ ]
393
+ );
394
+
395
+ if ($errors->count() != 0) {
396
+ foreach ($errors as $error) {
397
+ $log[] = $error->getMessage();
398
+ }
399
+ }
356
400
 
357
- return $this->json(['success' => true, 'log' => $log]);
358
- } catch (\Exception $e) {
359
- $log = $e->getMessage();
360
- log_error($e);
401
+ $errors = $this->validator->validate(
402
+ $version,
403
+ [
404
+ new Assert\NotBlank(),
405
+ new Assert\Regex(
406
+ [
407
+ 'pattern' => '/^[0-9.]+$/',
408
+ ]
409
+ ),
410
+ ]
411
+ );
412
+
413
+ if ($errors->count() != 0) {
414
+ foreach ($errors as $error) {
415
+ $log[] = $error->getMessage();
416
+ }
417
+ }
418
+
419
+ if (empty($log)) {
420
+ try {
421
+ $log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);
422
+
423
+ return $this->json(['success' => true, 'log' => $log]);
424
+ } catch (\Exception $e) {
425
+ $log = $e->getMessage();
426
+ log_error($e);
427
+ }
361
428
  }
362
429
 
363
430
  return $this->json(['success' => false, 'log' => $log], 500);

修正方法2-2: 修正差分を確認して適用する場合(4.1系)

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

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

修正差分

src/Eccube/Controller/Admin/Store/OwnerStoreController.php CHANGED
@@ -32,6 +32,8 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
32
32
  use Symfony\Component\HttpFoundation\Request;
33
33
  use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
34
34
  use Symfony\Component\Routing\Annotation\Route;
35
+ use Symfony\Component\Validator\Constraints as Assert;
36
+ use Symfony\Component\Validator\Validator\ValidatorInterface;
35
37
 
36
38
  /**
37
39
  * @Route("/%eccube_admin_route%/store/plugin/api")
@@ -63,6 +65,11 @@ class OwnerStoreController extends AbstractController
63
65
  */
64
66
  protected $pluginApiService;
65
67
 
68
+ /**
69
+ * @var ValidatorInterface
70
+ */
71
+ protected $validator;
72
+
66
73
  private static $vendorName = 'ec-cube';
67
74
 
68
75
  /** @var BaseInfo */
@@ -81,6 +88,7 @@ class OwnerStoreController extends AbstractController
81
88
  * @param PluginApiService $pluginApiService
82
89
  * @param BaseInfoRepository $baseInfoRepository
83
90
  * @param CacheUtil $cacheUtil
91
+ * @param ValidatorInterface $validatorInterface
84
92
  *
85
93
  * @throws \Doctrine\ORM\NoResultException
86
94
  * @throws \Doctrine\ORM\NonUniqueResultException
@@ -92,7 +100,8 @@ class OwnerStoreController extends AbstractController
92
100
  SystemService $systemService,
93
101
  PluginApiService $pluginApiService,
94
102
  BaseInfoRepository $baseInfoRepository,
95
- CacheUtil $cacheUtil
103
+ CacheUtil $cacheUtil,
104
+ ValidatorInterface $validatorInterface
96
105
  ) {
97
106
  $this->pluginRepository = $pluginRepository;
98
107
  $this->pluginService = $pluginService;
@@ -100,6 +109,7 @@ class OwnerStoreController extends AbstractController
100
109
  $this->pluginApiService = $pluginApiService;
101
110
  $this->BaseInfo = $baseInfoRepository->get();
102
111
  $this->cacheUtil = $cacheUtil;
112
+ $this->validator = $validatorInterface;
103
113
 
104
114
  // TODO: Check the flow of the composer service below
105
115
  $this->composerService = $composerService;
@@ -263,14 +273,32 @@ class OwnerStoreController extends AbstractController
263
273
 
264
274
  $pluginCode = $request->get('pluginCode');
265
275
 
266
- $log = null;
267
- try {
268
- $log = $this->composerService->execRequire('ec-cube/'.$pluginCode);
269
-
270
- return $this->json(['success' => true, 'log' => $log]);
271
- } catch (\Exception $e) {
272
- $log = $e->getMessage();
273
- log_error($e);
276
+ $errors = $this->validator->validate(
277
+ $pluginCode,
278
+ [
279
+ new Assert\NotBlank(),
280
+ new Assert\Regex(
281
+ [
282
+ 'pattern' => '/^[a-zA-Z0-9_]+$/',
283
+ ]
284
+ ),
285
+ ]
286
+ );
287
+
288
+ if ($errors->count() != 0) {
289
+ $log = [];
290
+ foreach ($errors as $error) {
291
+ $log[] = $error->getMessage();
292
+ }
293
+ } else {
294
+ try {
295
+ $log = $this->composerService->execRequire('ec-cube/'.$pluginCode);
296
+
297
+ return $this->json(['success' => true, 'log' => $log]);
298
+ } catch (\Exception $e) {
299
+ $log = $e->getMessage();
300
+ log_error($e);
301
+ }
274
302
  }
275
303
 
276
304
  return $this->json(['success' => false, 'log' => $log], 500);
@@ -344,14 +372,53 @@ class OwnerStoreController extends AbstractController
344
372
  $pluginCode = $request->get('pluginCode');
345
373
  $version = $request->get('version');
346
374
 
347
- $log = null;
348
- try {
349
- $log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);
375
+ $log = [];
376
+
377
+ $errors = $this->validator->validate(
378
+ $pluginCode,
379
+ [
380
+ new Assert\NotBlank(),
381
+ new Assert\Regex(
382
+ [
383
+ 'pattern' => '/^[a-zA-Z0-9_]+$/',
384
+ ]
385
+ ),
386
+ ]
387
+ );
388
+
389
+ if ($errors->count() != 0) {
390
+ foreach ($errors as $error) {
391
+ $log[] = $error->getMessage();
392
+ }
393
+ }
350
394
 
351
- return $this->json(['success' => true, 'log' => $log]);
352
- } catch (\Exception $e) {
353
- $log = $e->getMessage();
354
- log_error($e);
395
+ $errors = $this->validator->validate(
396
+ $version,
397
+ [
398
+ new Assert\NotBlank(),
399
+ new Assert\Regex(
400
+ [
401
+ 'pattern' => '/^[0-9.]+$/',
402
+ ]
403
+ ),
404
+ ]
405
+ );
406
+
407
+ if ($errors->count() != 0) {
408
+ foreach ($errors as $error) {
409
+ $log[] = $error->getMessage();
410
+ }
411
+ }
412
+
413
+ if (empty($log)) {
414
+ try {
415
+ $log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);
416
+
417
+ return $this->json(['success' => true, 'log' => $log]);
418
+ } catch (\Exception $e) {
419
+ $log = $e->getMessage();
420
+ log_error($e);
421
+ }
355
422
  }
356
423
 
357
424
  return $this->json(['success' => false, 'log' => $log], 500);

修正方法2-3: 修正差分を確認して適用する場合(4.2系)

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

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

修正差分

src/Eccube/Controller/Admin/Store/OwnerStoreController.php CHANGED
@@ -32,6 +32,8 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
32
32
  use Symfony\Component\HttpFoundation\Request;
33
33
  use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
34
34
  use Symfony\Component\Routing\Annotation\Route;
35
+ use Symfony\Component\Validator\Constraints as Assert;
36
+ use Symfony\Component\Validator\Validator\ValidatorInterface;
35
37
 
36
38
  /**
37
39
  * @Route("/%eccube_admin_route%/store/plugin/api")
@@ -48,6 +50,11 @@ class OwnerStoreController extends AbstractController
48
50
  */
49
51
  protected $pluginService;
50
52
 
53
+ /**
54
+ * @var ValidatorInterface
55
+ */
56
+ protected ValidatorInterface $validator;
57
+
51
58
  /**
52
59
  * @var ComposerServiceInterface
53
60
  */
@@ -81,6 +88,7 @@ class OwnerStoreController extends AbstractController
81
88
  * @param PluginApiService $pluginApiService
82
89
  * @param BaseInfoRepository $baseInfoRepository
83
90
  * @param CacheUtil $cacheUtil
91
+ * @param ValidatorInterface $validatorInterface
84
92
  *
85
93
  * @throws \Doctrine\ORM\NoResultException
86
94
  * @throws \Doctrine\ORM\NonUniqueResultException
@@ -92,7 +100,8 @@ class OwnerStoreController extends AbstractController
92
100
  SystemService $systemService,
93
101
  PluginApiService $pluginApiService,
94
102
  BaseInfoRepository $baseInfoRepository,
95
- CacheUtil $cacheUtil
103
+ CacheUtil $cacheUtil,
104
+ ValidatorInterface $validatorInterface
96
105
  ) {
97
106
  $this->pluginRepository = $pluginRepository;
98
107
  $this->pluginService = $pluginService;
@@ -100,6 +109,7 @@ class OwnerStoreController extends AbstractController
100
109
  $this->pluginApiService = $pluginApiService;
101
110
  $this->BaseInfo = $baseInfoRepository->get();
102
111
  $this->cacheUtil = $cacheUtil;
112
+ $this->validator = $validatorInterface;
103
113
 
104
114
  // TODO: Check the flow of the composer service below
105
115
  $this->composerService = $composerService;
@@ -263,13 +273,32 @@ class OwnerStoreController extends AbstractController
263
273
 
264
274
  $pluginCode = $request->get('pluginCode');
265
275
 
266
- try {
267
- $log = $this->composerService->execRequire('ec-cube/'.$pluginCode);
276
+ $errors = $this->validator->validate(
277
+ $pluginCode,
278
+ [
279
+ new Assert\NotBlank(),
280
+ new Assert\Regex(
281
+ [
282
+ 'pattern' => '/^[a-zA-Z0-9_]+$/',
283
+ ]
284
+ ),
285
+ ]
286
+ );
287
+
288
+ if ($errors->count() != 0) {
289
+ $log = [];
290
+ foreach ($errors as $error) {
291
+ $log[] = $error->getMessage();
292
+ }
293
+ } else {
294
+ try {
295
+ $log = $this->composerService->execRequire('ec-cube/'.$pluginCode);
268
296
 
269
- return $this->json(['success' => true, 'log' => $log]);
270
- } catch (\Exception $e) {
271
- $log = $e->getMessage();
272
- log_error($e);
297
+ return $this->json(['success' => true, 'log' => $log]);
298
+ } catch (\Exception $e) {
299
+ $log = $e->getMessage();
300
+ log_error($e);
301
+ }
273
302
  }
274
303
 
275
304
  return $this->json(['success' => false, 'log' => $log], 500);
@@ -343,13 +372,53 @@ class OwnerStoreController extends AbstractController
343
372
  $pluginCode = $request->get('pluginCode');
344
373
  $version = $request->get('version');
345
374
 
346
- try {
347
- $log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);
375
+ $log = [];
376
+
377
+ $errors = $this->validator->validate(
378
+ $pluginCode,
379
+ [
380
+ new Assert\NotBlank(),
381
+ new Assert\Regex(
382
+ [
383
+ 'pattern' => '/^[a-zA-Z0-9_]+$/',
384
+ ]
385
+ ),
386
+ ]
387
+ );
388
+
389
+ if ($errors->count() != 0) {
390
+ foreach ($errors as $error) {
391
+ $log[] = $error->getMessage();
392
+ }
393
+ }
348
394
 
349
- return $this->json(['success' => true, 'log' => $log]);
350
- } catch (\Exception $e) {
351
- $log = $e->getMessage();
352
- log_error($e);
395
+ $errors = $this->validator->validate(
396
+ $version,
397
+ [
398
+ new Assert\NotBlank(),
399
+ new Assert\Regex(
400
+ [
401
+ 'pattern' => '/^[0-9.]+$/',
402
+ ]
403
+ ),
404
+ ]
405
+ );
406
+
407
+ if ($errors->count() != 0) {
408
+ foreach ($errors as $error) {
409
+ $log[] = $error->getMessage();
410
+ }
411
+ }
412
+
413
+ if (empty($log)) {
414
+ try {
415
+ $log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version);
416
+
417
+ return $this->json(['success' => true, 'log' => $log]);
418
+ } catch (\Exception $e) {
419
+ $log = $e->getMessage();
420
+ log_error($e);
421
+ }
353
422
  }
354
423
 
355
424
  return $this->json(['success' => false, 'log' => $log], 500);

問い合わせ先

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

EC-CUBE 運営チーム
MAIL: [email protected]