
HikCentral Professional - 事前認証ライセンス ActiveCode 漏洩
何かをダウンロードする前に、既に公開されている情報:
| ソース | 分かること |
|---|---|
| Hikvision セキュリティアドバイザリ | 「APIエンドポイントでの認証チェック欠如」、V2.6.3 / V3.0.1 へのアップグレードを推奨 |
| NVD CVE-2025-39247 | CVSS メトリクス。ベクトルはネットワーク、認証不要、スコープ変更あり、機密性への影響は高 |
| Wiz、ZeroPath、SentinelOne、OffSeq、gbhackers、cybersecuritynews の要約 | すべてアドバイザリの言い換え。技術的詳細なし、PoC なし、影響を受けるエンドポイントの名称なし |
| GitHub の PoC アグリゲーター(poc-in-github、0xMarcio/cve など) | インデックスされた PoC なし |
| フォーラム(ipcamtalk、cctvforum、reddit)、トレントインデクサー | PoC なし、リークされたインストーラーなし。ipcamtalk には HikCentral の利用スレッドがあるが、エクスプロイト関連のものはなし |
したがって、分析日時点では、このバグを公開している技術的な解説書は存在しない。再現はバイナリ差分解析から始めることになる。
CVE-2025-39247 の公開後、V2.6.2 のダウンロードページは削除されたが、CDN 上のファイルは削除されていなかった。ファイル名は、削除前にページをインデックスしていたサードパーティのミラー(FileHorse — 公開ファイル名と MD5)から復元できる。そのファイル名を使い、通常のブラウザの User-Agent とそれに対応する Referer ヘッダーだけを用いて Hikvision の CDN にプレーンな GET リクエストを送ると、まだそのファイルが配信される。```bash
curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0"
-H "Referer: https://www.hikvision.com/en/support/download/software/hikcentral-professional-v2-6-2/"
-O
"https://www.hikvision.com/content/dam/hikvision/en/support/download/vms/hcp-2-6-2/HikCentral-Professional_Full-Pack_V2.6.2.202501211507_Win_x64_Installer.exe"
結果:
- サイズ: 1,314,043,792 バイト (1.22 GB)
- MD5: `76d42e7cb16dc0e177b9a35d0fed7ced` — FileHorseが公開している値と一致しており、正規のHikvision署名付きインストーラーであることを確認(サードパーティによる再バンドルではない)
- CDNレスポンスヘッダー: `HTTP/2 200`, `content-type: application/x-msdownload`, `eo-cache-status: HIT`, `age: 2520395` (≈ 29日間、Tencent EdgeOneエッジキャッシュに格納されたまま排除されていない)
**Hikvision PSIRTに報告する価値のある副次的な観察:** V2.6.2ページの「削除」は表面的なものです。孤児となったファイルは認証なし、署名付きURLのゲートなしでCDN上で到達可能です。V2.5.1 および V2.6.0 フルパックも同様に応答します。
### 2.2 パッチ適用済みインストーラー (V2.6.3 ベースパック)
現在V2.6.3のダウンロードページからリンクされています。取得方法は同じです:```
https://www.hikvision.com/content/dam/hikvision/en/support/download/vms/hcp-2-6-3/HikCentral-Professional_Base-Pack_V2.6.3.202508280142_Win_x64_Installer.exe
V2.6.2 のダウンロードページから引き続きリンクされています (Hikvision はユーザーに適用してほしいと考えています):``` https://www.hikvision.com/content/dam/hikvision/en/support/download/vms/cve-2025-39247-security-vulnerability-patch/HikCentral-Professional_CVE-2025-39247_FixPack_V2.3.1-V2.6.2V3.0.0_20250904.exe
- サイズ: 32,599,504 bytes (31 MB)
---
## 3. 静的抽出
3つはすべてInstallShieldスタイルのPEラッパーです。`7z`は2パスでそれらを展開します:```bash
# pass 1 — extract PE resources
7z x -o./extracted/v262/pe downloads/<v2.6.2 installer>
7z x -o./extracted/v263/pe downloads/<v2.6.3 installer>
# pass 2 — extract the nested 7-Zip streams hiding in PE resources
# (note: the resource-type label says "ZIP" but the byte signature is 7-Zip)
for ver in v262 v263; do
for z in extracted/$ver/pe/.rsrc/2052/ZIP/*; do
sz=$(stat -c %s "$z"); [ "$sz" -lt 1048576 ] && continue
7z x -o"extracted/$ver/payload/$(basename $z)" "$z"
done
done
両インストーラーは、それぞれ約24個の名前付きペイロードアーカイブに展開されます。トップレベルのディレクトリでアーキテクチャが明らかになります:
| Archive | Contents |
|---|---|
246/Nginx + 246/www | Nginx Web層(玄関口)とSPA Web UI |
244/bin | ネイティブC++サービスバイナリ + 証明書 |
240 | 同梱のPostgreSQL + DB初期化スクリプト |
238 | Bee* ランタイム(BeeAgent、BeeGuard、…) |
282 | アプリケーションサービスとアドオン(C++バックエンドコードの大部分) |
281, 283-284, 396, 398-399, 513, 520, 538-541, 573 | 小型のアドオン、プラグイン、アップグレード/アンインストール用スタブ |
重要なのは、JavaのJAR/WARがどこにも存在しないことです。バックエンドはNginx上のC++です。これは、認証の欠陥がコンパイル済みバイナリに存在し、逆コンパイルが容易なWAR/JARバイトコードには存在しないことを事前に示しているため重要です。
for ver in v262 v263: find . -type f -print0 | xargs -0 md5sum | sort -k2 > inv_$ver.txt
v262 = {ln[34:]: ln[:32] for ln in open("inv_v262.txt")} v263 = {ln[34:]: ln[:32] for ln in open("inv_v263.txt")} common = set(v262) & set(v263) changed = [p for p in common if v262[p] != v263[p]]
結果:共通パス内の239個の変更ファイル。分布:
| バケット | 数 | コメント |
|---|---|---|
| `246/www/*.js`(Web UIチャンク) | ~200 | ほとんどがバージョン更新によるアセットハッシュの変更。無視 |
| `246/Nginx/conf/nginx_location.conf` | **1** | **単一ファイルのNginx設定差分 — ここから始める** |
| `246/Nginx*/install.bat` | 6 | インストールスクリプト、無関係 |
| `244/bin/*.{exe,dll}` | 6 | ネイティブバイナリ(`DistributionFilter.dll`、`FilterChain.dll`、メディアツール) |
| `282/*.{exe,dll}` | 55 | アプリケーションサービス(最大のクラスター — `platform.dll`、`PersonCredential.dll`、`baseacs.*`、…) |
| `240/bin/pg_*` | 6 | Postgresの再ビルド、無関係 |
| `284/hplugin/dahua_plugin/*` | 4 | ベンダーSDKリフレッシュ(+10.97 MB)— 無関係 |
| `284/hplugin/onvif_plugin/*` | 4 | ベンダーSDKリフレッシュ(+0.99 MB)— 無関係 |
| upgrade/uninstallスタブ、クラッシュレポーター | ~30 | 同じサイズのPEタイムスタンプ再ビルド、無視 |
ベンダーSDKリフレッシュ、ビルドシステムのタイムスタンプずれ、純粋な外観上のアセット更新を除外すると、*実際の* セキュリティ関連の差分は以下に絞られます:
- 1つのNginx設定ファイル
- `282/` 内の少数のC++バイナリ(最も顕著なのは `platform.dll`、HCMPバックエンドサービス、+57 KB)
---
## 5. Nginxの差分:無料のバグ特定
V2.6.2とV2.6.3の間で `diff -u nginx_location.conf` を実行すると、ちょうど1つの差分ハンクが生成されます:V2.6.3に完全に新しい `location =` ブロックが追加されています。```nginx
#禁止非127.0.0.1和::1的重置密码 ← "Forbid non-127.0.0.1/::1 password reset"
location = /ISAPI/Bumblebee/Platform/V0/Permission/ChangeDefaultUserPassword {
if ($remote_addr ~ ^(127\.0\.0\.1|::1)$) { set $allowed 1; }
if ($allowed != "1") { return 403; }
if ($scheme = "http") { proxy_pass http://http_backend; }
if ($scheme = "https") { proxy_pass http://http2_backend; }
}
その21行だけの追加が、フロントドア層におけるCVE-2025-39247修正の全体であり、それだけで全てが分かります。
PUT /ISAPI/Bumblebee/Platform/V0/Permission/ChangeDefaultUserPassword/ISAPI/Bumblebee/Platform/V0/* プロキシディレクティブを通過してバックエンドに到達し、リモートアドレス制限がなく、Nginxレベルの認証チェックもありません。中国語のコメントが重要です。直訳すると「非127.0.0.1/::1からのパスワードリセットを禁止」となります。
Web UIのJavaScript(minified、246/www/Portal/*.js内)は、次のようにエンドポイントを呼び出します。```js
// API definition (de-minified):
changeDefaultUserPassword: function (sid, payload, opts) {
return http.put({
url: "ISAPI/Bumblebee/Platform/V0/Permission/ChangeDefaultUserPassword",
data: { ChangeDefaultUserPasswordRequest: payload },
params: { SID: sid }
}, opts);
}
// Call site: changeDefaultUserPassword(n.SID, { UserName: form.userName, // "admin" Password: jsEncrypt.encrypt(form.newPassword), // RSA-PKCS1v15 ActiveCode: form.activeCode ? jsEncrypt.encrypt(form.activeCode) : "", QuestionList: questionAnswers // [{ID, Answer}, …] or [] }, ...);
// The RSA pubkey comes from another unauthenticated endpoint: getCrypto: function () { http.get({ url: "ISAPI/Bumblebee/Platform/V0/Security/Crypto" }); } // returns: { CryptoKey: <PEM/base64 RSA pubkey>, ... }
したがって、何かを逆アセンブルする前から、公開されているJSだけで完全なワイヤーフォーマットが得られる。しかし、厄介な点も同時に明らかになる。リクエストボディには**有効な`ActiveCode`または正しい`QuestionList`の回答のいずれか**が必要であり、空の値を送信しても機能しない — バックエンドは文書化されたエラーのいずれかで拒否する(§7の`platform.dll`の文字列マイニングで確認済み)。
つまり、CVE-2025-39247は**「エンドポイントが認証バイパスであり、空のフィールドを送信すればパスワードが変更される」というものではない**。そうではなく、「エンドポイントは*ローカル専用の呼び出し元*がすでに正しいActiveCodeを持っていると*信頼*している。バグは、ネットワークレベルのlocalhostゲートが欠落していることだ。そのため、*リモート*の呼び出し元であっても、有効なActiveCodeまたはQuestionListを*併せて*供給できれば成功してしまう」というものである。したがって、実際のエクスプロイトの難問は次のとおりだ: ActiveCodeまたはQuestionListはどこから入手するのか。
---
## 7. バックエンドハンドラ — `platform.dll`の文字列マイニング
`platform.dll`はHCMPバックエンドサービスであり、V2.6.2では46.87 MB、V2.6.3では46.93 MB(+57 KB)です。すべてのルーティング文字列、ログフォーマット文字列、C++ RTTI / `__FUNCTION__`文字列が平文のまま含まれています。