Vulnerability Detail Report
Vulnerability Overview
- ZDID: ZD-2026-00960
- Vendor: 誠和國際股份有限公司, 悟空科技股份有限公司, 株式会社喜喜
- Title: 悟空科技股份有限公司 低權限後台帳號可繞過 RBAC,跨站存取逾 12 萬筆付費使用者敏感資料及管理功能
- Introduction: 後台存在 RBAC 與後端授權控管不足問題,低權限帳號可跨站別存取及操作多個原應僅限管理員或客服角色使用的後台功能,並取得相關敏感資料。 根據後台訂單統計資料,截至測試當日,台灣站與日本站合計共有 121,173 筆付費紀錄可能處於此授權漏洞的影響範圍內;此數字為紀錄筆數,不代表不重複使用者人數。
處理狀態
目前狀態
-
新提交
-
已審核
-
已通報
-
未回報修補狀況
-
未複測
-
公開
處理歷程
- 2026/07/28 10:25:30 : 新提交 (由 更新此狀態)
- 2026/07/28 10:58:00 : 新提交 (由 更新此狀態)
- 2026/07/28 11:54:58 : 新提交 (由 更新此狀態)
- 2026/08/03 12:57:17 : 審核完成 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2026/08/05 19:00:57 : 通報未回應 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2026/08/05 19:00:58 : 審核完成 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2026/08/05 19:00:58 : 通報未回應 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2026/09/27 03:00:15 : 公開 (由 HITCON ZeroDay 平台自動更新)
詳細資料
參考資料
OWASP Top 10 - 2017 A5 - Broken Access Control
https://www.owasp.org/index.php/Top_10-2017_A5-Broken_Access_Control
CWE-284: Improper Access Control
https://cwe.mitre.org/data/definitions/284.html
相關網址
https://helper.diyidphoto.com/orders
https://helper.diyidphoto.com/shipping
https://helper.diyidphoto.com/idphoto
https://helper.diyidphoto.com/gallery
https://helper.diyidphoto.com/stats
https://helper.diyidphoto.com/click-stats
https://helper.diyidphoto.com/photos-test
https://helper.diyidphoto.com/redis-test
https://helper.diyidphoto.com/queue-monitor
https://helper.diyidphoto.com/collections
https://helper.diyidphoto.com/free-codes
敘述
0. 摘要(Summary)
https://helper.diyidphoto.com/ 使用 PocketBase 作為其後端管理程式,且是 https://diyidphoto.com/zh-tw/ 與 https://jp.diyidphoto.com/ 的後台管理頁面。
而串聯未授權使用者可匿名建立後台帳號並任意指定 role與後台可被公開發現之漏洞:
- 任意使用者可匿名建立 PB user 帳號,請求中將
role參數設為空陣列("role": []),或者不帶role參數,即可建立一個未指派任何角色的低權限 PB user 帳號。 - 建立低權限 PB user 帳號後,連上後台管理頁面
https://helper.diyidphoto.com,使用相同帳號密碼即可登入。 - role 參數的值,可影響到後台左側管理控制板(admin panel)的功能顯示與否。
- 透過載入的 HTML 與 JavaScript bundle,可知道後台管理頁面裡的各個路徑、相對應的存取權限(例如
roles: ["admin", "tw-service", "jp-service"])與端點功能。
正常來說,未指派任何角色的低權限 PB user 帳號("role": [])不應能存取後台資料或執行任何 API。
然而測試後發現,只要知道後台管理頁面裡的路徑/端點,仍可直接跨台灣站與日本站存取應屬於 admin / tw-service / jp-service 的 module 與 API,包括:
/orders/shipping/idphoto/gallery/stats/click-stats/photos-test/redis-test/queue-monitor/collections/free-codes
且多個後端 API 也會回傳真實資料與可操作對應功能,例如:
- 使用者訂單資料,包括其上傳之原始照片、經處理後的證件照、姓名、Email、電話
- 使用者郵寄地址
- 重製碼的列表,與其新增與刪除功能
- 已上傳照片集的照片資料
- GCS bucket 物件之資料與值
- 網站營運統計資料
整體看起來,後台雖在左側管理控制板有依據 role 篩選是否可見相關功能,但後端授權檢查不足,導致低權限帳號仍有能力可跨站執行或存取僅限管理員(admin)或客服(service)角色的後台資料。
可能原因將放在後台身份驗證可被繞過中。
1. 受影響功能(Affected Feature)
-
功能:後台管理頁面與多個僅限管理員或客服角色使用的管理功能
-
存取條件:需要可登入後台的低權限 PB user 帳號(
"role": []) -
主要受影響路徑:
/orders/shipping/idphoto/gallery/stats/click-stats/photos-test/redis-test/queue-monitor/collections/free-codes
-
主要影響資料類型:
- 台日兩站之使用者訂單資料
- 台日兩站之使用者上傳的原始照片、經處理後的證件照、姓名、Email、電話
- 台灣站的使用者郵寄地址
- 台日兩站之使用者的支付細節(payment detail)
- 台日兩站所使用之重製碼
- GCS bucket 物件之資料
- 台日兩站之已上傳照片集的圖片、圖片連結與 token
- 台日兩站之網站營運統計資料
- 內部錯誤訊息洩漏
2. 漏洞驗證之前置條件(Preconditions for Verification)
- 需要擁有一個可登入
helper.diyidphoto.com後台的低權限 PB user 帳號("role": [])。可參考未授權使用者可匿名建立後台帳號並任意指定 role建立。 - 需要知道後台相關功能之路徑,以便登入後經由瀏覽器輸入路徑,或用 Burp Suite 等工具呼叫相關 API。可參考後台可被公開發現。
3. 重現步驟(Steps to Reproduce)與概念驗證(Proof of Concept)
以下重現步驟皆使用 Burp Suite 作為工具。
以下 PoC 僅整理我在實際測試中看到的重點證據。因為 HITCON 提交附件最多只能上傳 10 張圖,所以我只附足以證明主問題成立的必要代表性截圖。其餘我都有保留,若需要可再補充。
步驟 1:建立一個新低權限 PB user 帳號
- 在 Burp Suite 中的 Repeater,對以下端點發送建立帳號請求,在 body 中填入 email / password 並將
role欄位設為空陣列:
POST /api/pb/api/collections/users/records HTTP/2
Host: helper.diyidphoto.com
Content-Type: application/json
{
"email": "<Redacted_Email>",
"password": "<Redacted_Password>",
"passwordConfirm": "<Redacted_Password>",
"role": []
}
- 送出請求後,可在 response 中查看到新建立的 user record,以及
"role": []被保存。
{
"avatar": "",
"collectionId": "_pb_users_auth_",
"collectionName": "users",
"created": "<Created_Date_Time>",
"emailVisibility": false,
"id": "<Id>",
"name": "",
"role": [],
"updated": "<Updated_Date_Time>",
"username": "<Username>",
"verified": false
}
步驟 2:使用該帳號登入後台管理頁面
-
在 Burp Suite 的瀏覽器連上
https://helper.diyidphoto.com/login,並填入步驟 1 建立的 email / password 登入(或輸入步驟 1 的 username / password 登入)。 -
登入後,即可觀察到左側管理控制板未顯示任何功能,而右側則會是訂單查詢(
/orders)的相關功能,例如查詢特定日期、特定訂單等。
若稍微留意,可以發現在登入後、或進行接下來的重現步驟操作,左側管理控制板會有一瞬間可看到所有功能,接著未顯示任何功能。
- 點擊左上角 DIY 旁類似雙彎曲箭頭的按鈕,即可切換台灣站與日本站之後台功能。
步驟 3:直接存取訂單查詢(/orders)功能
-
在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/orders進入訂單查詢功能。 -
依日期或關鍵字查詢訂單,會發現低權限
"role": []帳號可讀取訂單相關資料,查看使用者上傳之原始照片、經處理後的證件照、姓名(日本站尤其明顯)、Email、電話(台灣站尤其明顯)。 -
低權限
"role": []帳號可修改使用者資料。- 開另一個無痕網頁連上台灣站
https://diyidphoto.com/zh-tw/或日本站https://jp.diyidphoto.com/,上傳測試圖片,並一路進行到跳轉付款頁面。 - 接著在
https://helper.diyidphoto.com/orders以日期進行訂單查詢。請注意,查詢台灣站訂單應在台灣站後台,與查詢日本站訂單應-點擊類似雙彎曲箭頭的按鈕-切換至日本站後台,否則會查詢不到。 - 點擊修改功能,編輯使用者姓名、email或手機(也可三者一起改)並完成修改,即可確認低權限
"role": []帳號可進行修改使用者姓名、email與手機等操作。
- 開另一個無痕網頁連上台灣站
-
退款、取消發票、重寄郵件等功能,由於本測試遵循最小影響原則,為避免影響正式環境及商業營運,因此本次未執行該操作,建議在修正漏洞時此類 API 需要一併檢查是否也有越權執行等相關問題。
-
藉由後台可被公開發現與 Burp Suite 的 Proxy 頁籤中的 HTTP history 可發現,本路徑之相關 API 功能如以下:
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
POST |
/api/orders/search/date?diy_type=tw |
依日期搜尋台灣站訂單,搜尋後可見使用者之 image URL / image token 等資料。在 2024-10-02 有第一筆台灣訂單資料,但可能為測試系統之資料。 |
POST |
/api/orders/search/date?diy_type=ja |
依日期搜尋日本站訂單,搜尋後可見使用者之 image URL / image token 等資料。在 2024-10-02 有第一筆日本訂單資料,但可能為測試系統之資料。 |
POST |
/api/orders/search?diy_type=tw |
依關鍵字搜尋台灣站訂單,搜尋後可見使用者之 image URL / image token 等資料。 |
POST |
/api/orders/search?diy_type=ja |
依關鍵字搜尋日本站訂單,搜尋後可見使用者之 image URL / image token 等資料。 |
GET |
/api/orders/resend-email/<OrderID>?diy_type=tw |
重寄郵件功能,使用未付款台灣站 OrderID 測試會回傳 {"error_code":6,"error_text":"訂單尚未付款","data":null} 。 |
GET |
/api/orders/resend-email/<OrderID>?diy_type=ja |
重寄郵件功能,使用未付款日本站 OrderID 測試會回傳 {"error_code":6,"error_text":"訂單尚未付款","data":null} 。 |
POST |
/api/orders/edit |
修改使用者資料功能。 |
POST |
/api/refund |
退款功能,此功能可導致解密後明文與使用者識別資訊外洩,詳見跨用途 token 可進入相同解析流程。 |
POST |
/api/cancel-invoice |
取消發票功能,此功能可導致解密後明文與使用者識別資訊外洩,詳見跨用途 token 可進入相同解析流程。 |
步驟 4:直接存取郵寄管理(/shipping)功能
-
在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/shipping進入郵寄管理功能。 -
可發現低權限
"role": []帳號可讀取當日郵寄資料,包括使用者姓名、電話、地址等高敏感資訊,也可點擊查詢郵遞區號功能以進行查詢。
這裡值得注意的是:
- 日本站後台的管理控制板並沒有
/shipping功能,而若在日本站後台進入/shipping會看見台灣站的郵寄資料。 - 點擊「查詢郵遞區號」功能後,由 Burp Suite 可見使用者之地址資料被送往第三方
zip5.5432.tw進行郵遞區號查詢,經測試後暫時排除第三方寫入郵遞區號時造成 XSS 等相關漏洞。 - 「標示為已郵寄功能」可能影響到商業營運,因此本次未執行該操作,建議在修正漏洞時一併檢查此功能是否也有越權執行等相關問題。
- 藉由後台可被公開發現與 Burp Suite 的 HTTP history 可發現,本路徑之相關 API 功能如以下:
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
GET |
/api/orders/mail/pending?diy_type=tw |
台灣站當日待寄郵件資料。 |
POST |
/api/orders/mail/mailed?diy_type=tw |
標示為已郵寄功能。 |
步驟 5:直接存取快洗證件照(/idphoto)功能
-
在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/idphoto進入快洗證件照功能。 -
依日期或關鍵字查詢訂單,會發現低權限
"role": []帳號可讀取訂單相關資料,包括使用者之證件照。
- 日本站後台的管理控制板並沒有
/idphoto功能,而若在日本站後台進入/idphoto會看見與台灣站相同的資料。 - 對訂單點擊「更多」再點擊「支付細節」,可查看該訂單之支付詳細資料(包括Email、Phone等資訊),而裡面也有「申請退款」與「作廢發票」功能;這兩者功能可能影響到商業營運,因此本次未執行該操作,建議在修正漏洞時此類 API 需要一併檢查是否也有越權執行等相關問題。
- 對訂單點擊「更多」再點擊「完整分析」,可查看該訂單的照片之 AI 分析數據。
- 「重設列印」功能可能影響到商業營運,因此本次未執行該操作,建議在修正漏洞時此類 API 需要一併檢查是否也有越權執行等相關問題。
這裡值得注意的是:
- 根據
/idphoto此端點的可見資料,會發現照片量相對不多且皆集中在非假日(週六日)上傳,看起來像是仍在測試中。 -
在訂單的「支付細節」裡,有一個資料欄位是
RequestJSON,點擊查看數據,可發現webhook參數中可見https://qkidphoto.goqoo.com/complete?order_id=...&token=...這連結。- 透過 Google dork
site:qkidphoto.goqoo.com進行查詢,未發現該網域的公開索引結果。
- 透過 Google dork
-
另一個無痕網頁連上
https://qkidphoto.goqoo.com這網址,上傳測試圖片,並一路進行到付款頁面。-
藉由 Burp Suite 的 HTTP history 可發現,此網址的圖片上傳方式與台灣站
https://diyidphoto.com/zh-tw/和日本站https://jp.diyidphoto.com/不同。 -
https://qkidphoto.goqoo.com是使用 POST multipart/form-data 作為方法 -
https://diyidphoto.com/zh-tw/和https://jp.diyidphoto.com/是使用 WebSocket 作為方法 -
因此,
https://qkidphoto.goqoo.com比較像https://diy.goqoo.com.tw/QKPhoto/Chi/MainMenu.php相關端點(例如/QKPhoto/Chi/UploadFile6.php?ano=...或/QKPhoto/Chi/UploadFile7.php?ano=...,詳細路徑可見訂單流程參數存在 IDOR) 所用之方式
-
-
詳細比較
https://qkidphoto.goqoo.com與https://diy.goqoo.com.tw/QKPhoto/Chi/MainMenu.php相關端點的行為差異,會發現:-
https://qkidphoto.goqoo.com在上傳圖片時會給一組不可預測、或難以預測之 order_id 與 token,此行為像是https://diyidphoto.com/zh-tw/和https://jp.diyidphoto.com/ -
但
https://qkidphoto.goqoo.com之OrderID為 8 碼,台日兩站OrderID為 7 碼 -
https://diy.goqoo.com.tw/QKPhoto/Chi/MainMenu.php相關端點會給遞增且可預測之 ano / AlbumNo 參數(因而造成 IDOR) -
因此推測
https://qkidphoto.goqoo.com這網址可能是為了修正 IDOR 漏洞、或將其融進後台系統中而開發
-
- 藉由後台可被公開發現與 Burp Suite 的 HTTP history 可發現,本路徑之相關 API 功能如以下:
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
GET |
/api/idphoto/orders?start=<Start_Date_Time>&end=<End_Date_Time> |
依日期搜尋 https://qkidphoto.goqoo.com 訂單,搜尋後可見使用者之 order_id / token 等資料。在 2026-04-28 有第一筆訂單資料,但可能為測試系統之資料。 |
GET |
/api/idphoto/orders?search=<Key_Word> |
依關鍵字搜尋 https://qkidphoto.goqoo.com 訂單,搜尋後可見使用者之 order_id / token 等資料。 |
GET |
/api/idphoto/img?order_id=<goqoo_OrderID>&token=<goqoo_Token>&photo_type=<Photo_Type> |
可查看 https://qkidphoto.goqoo.com 使用者之證件照。Photo_Type 為 1 或 2 目前看不出證件照的差別,為 3 會是附有尺規之證件照。 |
GET |
/api/order/<goqoo_OrderID>/payment |
支付細節功能,可查看特定訂單的支付細節(payment detail)。由於此端點 <goqoo_OrderID> 處也可填入 https://diyidphoto.com/zh-tw/ 或 https://jp.diyidphoto.com/ 之 OrderID,因此可被用於日本站特定付款方式可被注入外部網域、台灣站與日本站付款流程綁定不足與未付款訂單存取控制不一致。 |
POST |
/api/order/<goqoo_OrderID>/payment/refund?&token=<goqoo_Token> |
https://qkidphoto.goqoo.com 訂單之退款功能,使用未付款 order_id / token 測試會回傳 {"error_code":2,"error_text":"未付款","data":null} 。 |
POST |
/api/order/<goqoo_OrderID>/invoice/cancel?remark= |
https://qkidphoto.goqoo.com 訂單之取消發票功能,使用未付款 order_id / token 測試會回傳 {"error_code":9923,"error_text":"取得訂單發票錯誤: record not found","data":null} 。 |
PATCH |
/api/idphoto/<goqoo_OrderID>/print/reset |
https://qkidphoto.goqoo.com 訂單之重設列印狀態功能,可能會影響該筆訂單之參數 print_status 的值,但使用未付款 order_id 測試則仍是 "print_status":0。 |
步驟 6:直接存取已上傳照片集(/gallery)功能
-
在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/gallery進入已上傳照片集功能。 -
可發現低權限
"role": []帳號可讀取當日使用者上傳之原始照片與經處理後的照片。
這裡值得注意的是:
- 台灣站
https://diyidphoto.com/zh-tw/和日本站https://jp.diyidphoto.com/上傳的照片都會出現在此,因此/gallery端點可能保存了兩站的照片內容。 - 未付款訂單會被標註綠字的
準備付款標籤,可被用於未付款訂單存取控制不一致與日本站資料保存情形可能與常見問題不一致。
-
調整日期,即可發現低權限
"role": []帳號可讀取調整的日期的照片。 -
藉由後台可被公開發現與 Burp Suite 的 HTTP history 可發現,本路徑之相關 API 功能如以下:
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
POST |
/api/gallery/list?site=tw |
依日期(參數Date)搜尋台灣站與日本站之訂單,搜尋後可見使用者之 gallery image URL / gallery image token 與 "PrePay":true/false 等資料。在 2022-01-05 有第一筆訂單資料,但可能為測試系統之資料。此端點列出之 gallery image URL / gallery image token 可被用於跨用途 token 可進入相同解析流程。而 "PrePay":true 可被用於未付款訂單存取控制不一致與日本站資料保存情形可能與常見問題不一致。 |
步驟 7:直接存取數據統計(/stats) 與點擊統計 (/click-stats)功能
-
在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/stats進入數據統計功能,即可發現低權限"role": []帳號可讀取網站營運統計資料,且可使用相關功能,例如調整日期、免費/付費、日/月/年、台灣站/日本站,獲取更詳細的網站營運統計數據。 -
在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/click-stats進入點擊統計功能,即可發現低權限"role": []帳號可讀取日本站重製碼的點擊統計資料,且可使用相關功能,例如調整日期區間獲取更詳細的日本站重製碼統計數據。
-
日本站後台的管理控制板沒有
/stats與/click-stats功能。 -
藉由後台可被公開發現與 Burp Suite 的 HTTP history 可發現,以上兩者路徑之相關 API 功能如以下:
訂單統計(/stats)
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
GET |
/api/orders/stats?start=<Start_Date_Time>&end=<End_Date_Time>&group_by=<Day_Month_Year>&diy_type=<TW_Or_JA>&free=<0_Or_1> |
diyidphoto之訂單統計功能。由此功能可知,直至今日報告完成時,後台權限漏洞(例如本報告、未授權使用者可匿名建立後台帳號並任意指定 role與後台身份驗證可被繞過)可洩漏 / 影響台日兩站共計 121,173 筆之付費使用者資料。 |
GET |
/api/idphoto/stats?start=<Start_Date_Time>&end=<End_Date_Time>&group_by=<Day_Month_Year>&diy_type=<TW_Or_JA>&free=<0_Or_1>&product_type=<Number> |
idphoto之訂單統計功能。 |
JP share-code 點擊統計(/click-stats)
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
GET |
/api/click/jp-share-code?start=<Start_Date_Time>&end=<End_Date_Time> |
JP share-code 點擊統計功能。 |
步驟 8:直接存取照片測試(/photos-test)功能
-
在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/photos-test進入照片測試功能。 -
可發現低權限
"role": []帳號可讀取 / 進入列出的資料夾,其中包括anime與diyidphoto等。 -
進入任一資料夾,點擊「探索此目錄下的檔案」功能,會發現低權限
"role": []帳號可列出該資料夾內的檔案內容;而就目前測試結果,幾乎都是後台的測試照片。
- 藉由後台可被公開發現與 Burp Suite 的 HTTP history 可發現,本路徑之相關 API 功能如以下:
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
GET |
/api/unit-test/list-folders/ |
列出測試照片功能裡的所有資料夾,能以同樣方式進入子資料夾並列出其中的資料夾,例如 GET /api/unit-test/list-folders/<subdir>/ 。 |
GET |
/api/unit-test/list-files/ |
列出測試照片功能裡的所有檔案,但不建議這樣做,資料會過於龐大;建議使用的方式為進入子資料夾後再列出,例如 GET /api/unit-test/list-files/<subdir>/ 。 |
這裡值得注意的是:
-
端點
/api/unit-test/list-files/的 Response 中含有 GCS bucket 物件之資料與值,包括以下:- Bucket
- Name
- ContentType
- Owner
- Size
- ContentEncoding
- ContentDisposition
- MD5
- CRC32C
- MediaLink
- Metadata
- Generation
- StorageClass
- Created / Deleted / Updated
- CustomerKeySHA256
- Etag
- CustomTime
其中,雖不能直接由 MediaLink 之連結 https://storage.googleapis.com/download/storage/v1/b/... 直接讀取圖片,但可透過 https://helper.diyidphoto.com/api/unit-test/img/ 加上 Name 之路徑,即可以低權限 "role": [] 帳號查看該圖片。
步驟 9:直接存取 Redis 測試(/redis-test)功能
-
在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/redis-test進入 Redis 測試功能。 -
可發現低權限
"role": []帳號可進入,且在 Queue Key 欄位輸入值,其會顯示在Redis Preview上;但本測試採最低限度,因此沒有按下「送出請求」按鈕,建議在修正漏洞時此類 API 需要一併檢查是否也有越權執行等相關問題。
- 藉由後台可被公開發現可發現,本路徑之相關 API 功能包含以下:
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
POST |
/api/job/redis |
從程式中看起來像在測試或檢視 AI 是否有正常處理使用者上傳的圖片。 |
步驟 10:直接存取佇列監控(/queue-monitor)功能
-
在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/queue-monitor進入佇列監控功能。 -
可發現低權限
"role": []帳號可進入,並監控以下 6 個 queue:
- diyTW
- diyJP
- detectTW
- detectBoca
- relight
- photocutter
- 藉由後台可被公開發現與 Burp Suite 的 HTTP history 可發現,本路徑之相關 API 功能包含以下:
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
GET |
/api/queue/monitor |
若停留在 queue-monitor 頁面中,則每 5 秒會發送一次此請求,以取得各 queue 中的訂單資料。 |
步驟 11:直接存取集合管理(/collections)功能
- 在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/collections進入集合管理功能,即可發現:
- 會直接跳出錯誤訊息
獲取集合列表失敗: Error 1146 (42S02): Table 'diyidphoto.prod_collections' doesn't exist。 - 點擊「新增集合」功能,填妥相關資訊並點擊確認建立後,也會跳出錯誤訊息
建立集合失敗:Error 1146 (42S02):Table 'diyidphoto.prod_collections' doesn't exist。 - 此狀況無論是
"role": []或role:["admin"]皆會發生,因此暫時推測這可能是網站後台頁面並未使用此功能、或使用其它方式以替代此功能而產生的結果。
- 藉由後台可被公開發現與 Burp Suite 的 HTTP history 可發現,本路徑之相關 API 功能包含以下:
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
GET |
/api/collections/names |
集合管理功能,應會顯示所有集合,但請求後會回傳 {"error_code":9923,"error_text":"Error 1146 (42S02): Table 'diyidphoto.prod_collections' doesn't exist","data":null} 。 |
GET |
/api/collections?name=<Collections_Name> |
請求特定集合,但請求後會回傳 {"error_code":9923,"error_text":"Error 1146 (42S02): Table 'diyidphoto.prod_collections' doesn't exist","data":null} 。 |
POST |
/api/collections |
新增集合,但會回傳 {"error_code":9924,"error_text":"Error 1146 (42S02): Table 'diyidphoto.prod_collections' doesn't exist","data":null} 。 |
步驟 12:直接存取新增重製碼(/free-codes)功能
-
在登入狀態下,在瀏覽器的網址列輸入
https://helper.diyidphoto.com/free-codes進入新增重製碼功能。 -
可發現低權限
"role": []帳號可讀取所有重製碼清單。 -
點擊「產生重製碼」,即可新增一個重製碼;在該重製碼的操作欄位有一個垃圾桶 icon,點擊後按確認,即可將該重製碼刪除。此行為證明低權限
"role": []帳號可使用產生及刪除重製碼功能。
這裡值得注意的是,台日兩站後台應是共用相同重製碼清單,因為無論在哪一站新增或刪除重製碼,另一站皆會出現或消失該重製碼。
- 藉由後台可被公開發現與 Burp Suite 的 HTTP history 可發現,本路徑之相關 API 功能如以下:
| Method | Endpoint | 功能與驗證結果 |
|---|---|---|
GET |
/api/free-code?diy_type=tw |
重製碼清單。 |
POST |
/api/free-code?diy_type=tw |
新增重製碼。 |
DELETE |
/api/free-code/<Free-code_Id>?diy_type=tw |
刪除特定重製碼 |
4. 預期行為(Expected Behavior)
低權限帳號不應能存取任何僅限管理員或客服角色使用的後台資料與功能,也不應能呼叫相關 API。伺服器應拒絕此類未經授權的請求,並回傳 401 Unauthorized 或 403 Forbidden。
5. 實際行為(Actual Behavior)
即使帳號為低權限 "role": [],仍可跨站別存取及操作多個後台 API 與管理功能,包括讀取敏感資料,以及修改使用者資料、產生與刪除重製碼等操作,顯示後台未落實伺服器端 RBAC 與授權檢查。
6. 影響(Impact)
此問題使低權限帳號未經授權即可存取/操作台日兩站後台之使用者高敏感資料、後台功能及網站營運統計資訊,可能風險包括:
- 台日兩站之使用者高敏感個資外洩,包括原始照片、證件照、郵寄地址、聯絡方式與付款方式等
- 網站重製碼外洩或被濫用
- 後台營運統計資料外洩
- GCS bucket 物件結構與其資料外洩
- 攻擊者利用後台資料進一步串聯其它漏洞或擴大攻擊面
7. 可能的根本原因(Likely Root Cause)
問題可能是後端未確實實施 RBAC (server-side RBAC enforcement),整體授權模型(authorization model)不完整。
可能原因包括:
- 後端 API 沒有在每個端點強制檢查 role,且高敏感資料沒有進行回應最小化(response minimization)或去識別化等操作
- 沒有預設直接拒絕 role 為空、缺少或未知的情況
- 前端 route / menu / button gating-例如管理控制面板(admin panel)-被當成主要安全邊界,卻未考慮其被繞過的狀況
- 後台將
role、pb_role、active_site等資訊當成授權標準,但這些參數的來源沒有被嚴格檢查與保護
8. 嚴重性評估(Severity Assessment)
嚴重(Critical)
理由:
- 低權限
"role": []帳號可跨站別存取及操作多個原應僅限管理員或客服角色使用的後台功能,包括讀取高度敏感資料、修改使用者資料,以及新增與刪除重製碼 - 影響範圍橫跨台日兩站,且影響資料多元,包括使用者訂單、郵寄功能、使用者上傳之原始照片與經網站處理後的證件照、payment 資料、網站重製碼、GCS bucket 物件與網站營運統計資料等
- 問題發生在後台管理系統,理應有嚴格的角色與站別限制
9. 補充說明(Researcher Note)
-
本報告之測試僅限確認漏洞存在,未進行批次化、大量化或自動化操作,也未進行破壞性操作。
-
由於此系統與技術牽涉到三家公司-台灣公司為誠和國際股份有限公司(
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. 所有後台 API 皆須確實實施後端權限檢查,不應只依賴前端 route / menu / button 隱藏。
2. 未經明確授權的後台帳號,例如 role 為空(`"role": []`)、缺少(missing role)或未知(unknown role)的情況應預設拒絕存取,且不可讀 admin / tw-service / jp-service 資料。
3. 後台帳號的實際權限,必須在後端以可信任且難以竄改的後端 session、token claims 或 staff mapping 判斷,而非以前端設定或回傳的 `pb_role`、`active_site`、`diy_type` 作為授權標準。
4. 建立明確的後台角色存取控制(RBAC matrix),每個 API 都應定義:
* 哪些 role 可讀
* 哪些 role 可寫
* 可存取哪個 site
* 可操作哪些 resource
* 可讀取哪些欄位
* 是否允許跨站別存取
5. 對任何高風險、高敏感與牽涉到營運狀態的端點和操作,應加入審計紀錄(audit log),例如以下功能:
* 退款功能
* 取消發票功能
* 重寄 email
* 郵寄資料
* 新增或刪除重製碼
* 存取與編輯使用者個資
* 存取使用者支付細節(payment detail)
* 存取使用者的 image token
6. 對 API 的回應做最小化或進行去識別化,且低權限或未經明確授權者不應取得不必要欄位,例如使用者的完整地址等資訊。
7. 無論是 image、gallery、payment、order 之 token 皆應具備明確範圍(scope),並綁定:
* 訂單(order)
* 使用者(user)
* 角色(role)
* 網站站別(site)
* 用途(purpose)
* 期限(expiration time)
8. 修補後應逐一驗證本報告列出之路徑與其相關 API 功能,確認低權限帳號與未經授權之帳號無法存取。