
CVE-2026-49060을 재현하기 위한 Docker 기반 실습 환경입니다. 이 취약점은 WooCommerce WordPress 플러그인용 Hippoo Mobile App에서 인증되지 않은 권한 상승 문제입니다. 취약한 버전 1.9.4와 패치된 버전 1.9.5를 Python PoC와 함께 비교합니다.
이 저장소는 WordPress 플러그인 Hippoo Mobile App for WooCommerce에 영향을 미치는 부적절한 권한 할당 취약점인 CVE-2026-49060을 재현 및 검증하기 위한 로컬 Docker 실습 환경을 포함하고 있습니다.
취약한 동작은 Hippoo의 복제된 REST API 네임스페이스를 통해 노출됩니다:```text /wc-hippoo/v1/ext/
취약한 대상에서는 인증되지 않은 방문자가 복제된 WordPress REST 사용자 경로에 접근하고, 인증되지 않은 HTTP 요청을 통해 관리자 사용자의 비밀번호를 업데이트할 수 있습니다. 패치된 대상에서는 동일한 요청이 `403 Forbidden`으로 차단됩니다.
이 실습은 두 가지 Hippoo 버전을 비교합니다:
| 서비스 | Hippoo 버전 | 목적 | URL |
| --------- | -------------: | ---------------------------- | ----------------------- |
| `vuln` | 1.9.4 | 취약 비교 대상 | `http://localhost:8081` |
| `patched` | 1.9.5 | 패치된 비교 대상 | `http://localhost:8082` |
시연된 취약점 체인은 다음과 같습니다:```text
Unauthenticated visitor
→ Hippoo cloned REST namespace
→ /wc-hippoo/v1/ext/wp/v2/users/<id>
→ vulnerable permission handling allows access
→ unauthenticated GET exposes user data
→ unauthenticated POST can update the selected user's password
→ patched version blocks the same request with 403 Forbidden
이 연구실은 Hippoo 1.9.4와 Hippoo 1.9.5를 사용하여 취약한 버전 대 패치된 버전의 권한 부여 동작을 검증합니다.
이 연구실은 의도적으로 로컬 Docker 서비스로 범위가 제한됩니다. 외부 시스템을 대상으로 하지 않으며, 지속성, 웹 셸, 악성 코드 또는 외부 콜백을 포함하지 않습니다.
| 주장 | 증거 | 이 실습 환경에서 확인 방법 |
|---|---|---|
CVE-2026-49060은 1.9.4 버전까지의 WooCommerce용 Hippoo 모바일 앱에 영향을 미칩니다. | 공개 권고사항은 1.9.4 이하 / 1.9.4까지의 Hippoo가 영향을 받는 것으로 식별합니다. | 참고 자료 섹션을 검토하고 vuln 서비스 버전과 비교합니다. |
Hippoo 1.9.5는 패치된 비교 대상으로 사용됩니다. | 공개 권고사항 메타데이터는 1.9.5가 영향을 받는 범위에 대한 패치된 버전임을 식별합니다. | docker compose logs init-vuln init-patched를 실행하고 초기화된 플러그인 버전을 확인합니다. |
| 취약한 동작은 Hippoo의 복제된 REST 네임스페이스를 통해 노출됩니다. | Hippoo는 /wc-hippoo/v1/ext/ 아래에 외부 REST 경로를 다시 등록합니다. | python3 poc/poc.py http://127.0.0.1:8081 http://127.0.0.1:8082를 실행합니다. |
이 연구실에서 Hippoo 1.9.4는 복제된 사용자 경로에 대한 인증되지 않은 접근을 허용합니다. | 연구실 PoC는 http://127.0.0.1:8081/?rest_route=/wc-hippoo/v1/ext/wp/v2/users/1에서 200 OK를 받습니다. | 8081에 대해 읽기 전용 검증 명령을 실행합니다. |
이 연구실에서 Hippoo 1.9.5는 동일한 인증되지 않은 요청을 차단합니다. | 연구실 PoC는 http://127.0.0.1:8082/?rest_route=/wc-hippoo/v1/ext/wp/v2/users/1에서 403 Forbidden을 받습니다. | 8082에 대해 읽기 전용 검증 명령을 실행합니다. |
| 이 로컬 연구실에서 취약한 대상은 인증되지 않은 POST를 통해 관리자 비밀번호를 업데이트할 수 있습니다. | 활성 PoC는 --update-password가 사용될 때 취약한 대상에서 200 OK를 받습니다. | python3 poc/poc.py --update-password http://127.0.0.1:8081을 실행합니다. |
| 패치된 대상은 인증되지 않은 비밀번호 업데이트 요청을 차단합니다. | Hippoo 1.9.5는 동일한 복제된 사용자 경로에 대해 금지 응답을 반환합니다. | 두 대상 모두에 대해 활성 검증을 실행합니다. |
| PoC는 HTTP 전용입니다. | poc/poc.py는 HTTP 요청만 보내며 Docker, WP-CLI 또는 컨테이너 API를 호출하지 않습니다. | poc/poc.py를 검사합니다. |
이 연구실은 공개 권고사항이 1.9.4까지의 버전을 영향을 받는 것으로 식별하기 때문에 취약한 비교 대상으로 Hippoo 1.9.4를 사용합니다.
이 연구실은 공개 권고사항 메타데이터가 1.9.5를 시연된 영향 범위에 대한 수정 버전으로 식별하기 때문에 패치된 비교 대상으로 Hippoo 1.9.5를 사용합니다.
공개 CVE-2026-49060 기록은 이 문제를 높은 수준에서 잘못된 권한 할당/권한 상승으로 설명합니다. 이 연구실은 Hippoo 1.9.4의 관찰 가능한 권한 부여 동작에 초점을 맞추고 이를 Hippoo 1.9.5와 비교합니다.
이 README의 근본 원인 요약은 연구실에서 사용된 취약한 버전과 패치된 Hippoo 버전 간의 소스 비교를 기반으로 합니다.
이 연구실은 모든 Hippoo 경로를 테스트한다고 주장하지 않습니다. 복제된 WordPress 사용자 REST 경로에 초점을 맞춥니다:```text /wc-hippoo/v1/ext/wp/v2/users/
The lab does not demonstrate:
* 지속성,
* 웹 셸 업로드,
* 임의 명령 실행,
* 외부 콜백,
* 악성코드 동작,
* 비실험실 시스템에 대한 공격,
* 또는 로컬 비밀번호 업데이트 검증을 넘어선 손상 후 활동.
## 근본 원인 요약
근본 원인은 Hippoo의 역할 및 권한 처리에서의 권한 논리 결함입니다.
Hippoo는 자체 네임스페이스 아래에 복제된 WordPress 및 WooCommerce REST 라우트를 노출합니다:```text
/wc-hippoo/v1/ext/
The route-cloning behavior is security-sensitive because the cloned route must preserve or strengthen the original route's authorization requirements. If the cloned route receives a permissive permission callback, unauthenticated users may be able to reach REST endpoints that should require authentication and authorization.
The relevant route-cloning behavior follows this pattern:```php function re_register_external_routes() { $server = rest_get_server(); $endpoints = $server->get_routes();
$new_namespace = $this->hippoo_namespace . '/ext';
foreach ($endpoints as $route => $handlers) {
if (strpos($route, $this->hippoo_namespace) === 0) {
continue;
}
foreach ($handlers as $handler) {
$default_permission_callback = array($this, 'is_user_wordpress_admin');
$permission_callback = apply_filters(
'hippoo_extension_permission_check',
$default_permission_callback,
$route,
$handler
);
register_rest_route(
$new_namespace,
$route,
array(
'methods' => $methods,
'callback' => $handler['callback'],
'args' => $handler['args'],
'permission_callback' => $permission_callback,
)
);
}
}
}
의도된 보안 모델은:```text
Original protected REST route
→ cloned into Hippoo namespace
→ permission callback still denies unauthenticated access
취약한 동작은 Hippoo 1.9.4가 두 가지 다른 상태에 대해 동일한 반환 값을 사용하기 때문에 발생합니다:```text
administrator / unrestricted access
unauthenticated visitor / no user
Hippoo `1.9.4`에서 권한 도우미는 로그인된 WordPress 사용자가 없을 때 `null`을 반환합니다:```php
public static function get_user_permissions()
{
$user = wp_get_current_user();
if (empty($user) || !$user->exists()) {
return null;
}
if (in_array('administrator', (array) $user->roles)) {
return null; // Full access
}
$settings = get_option('hippoo_permissions_settings', []);
foreach ((array) $user->roles as $role) {
if (!isset($settings[$role])) {
continue;
}
return $settings[$role];
}
return null; // Full access
}
취약한 버전은 또한 null을 허용된 것으로 처리합니다:```php
private function has_role_access($section, $key = null)
{
$perms = self::get_user_permissions();
if ($perms === null) {
return true; // admin or unrestricted
}