Vulnerability Detail Report
Vulnerability Overview
- ZDID: ZD-2026-00806
- Vendor: SITCON 學生計算機年會
- Title: SITCON 學生計算機年會 tickets event form-field handlers continue after failed event access
- Introduction: Several public SITCON tickets event form-field admin handlers manually call requireEventAccess but continue into read/write logic after the guard sends a denial response.
處理狀態
目前狀態
-
新提交
-
已審核
-
已通報
-
已修補
-
未複測
-
公開
處理歷程
- 2026/06/03 19:45:09 : 新提交 (由 老狼 更新此狀態)
- 2026/06/10 12:48:12 : 審核中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2026/09/18 15:32:03 : 已修補 (由 組織帳號 更新此狀態)
- 2026/09/19 03:00:07 : 公開 (由 HITCON ZeroDay 平台自動更新)
詳細資料
- ZDID:ZD-2026-00806
- 通報者:skyknow (老狼)
- 風險:中
- 類型:存取控制缺陷 (Broken Access Control)
參考資料
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://github.com/sitcon-tw/tickets
https://github.com/sitcon-tw/tickets/blob/db4a3500c0331bdc5c204808399c52aa024b87e8/backend/routes/admin/eventFormFields.ts
https://github.com/sitcon-tw/tickets/blob/db4a3500c0331bdc5c204808399c52aa024b87e8/backend/middleware/auth.ts#L151-L181
https://github.com/sitcon-tw/tickets/blob/db4a3500c0331bdc5c204808399c52aa024b87e8/backend/routes/admin.ts#L17
敘述
Summary
The public sitcon-tw/tickets backend allows both admin and eventAdmin roles into the /api/admin router through requireAdminOrEventAdmin.
Several event form-field admin handlers then call requireEventAccess manually inside the handler body. When requireEventAccess denies an eventAdmin that is not authorized for the target event, it sends a denial response, but the caller does not check reply.sent or immediately return before continuing.
If the deployed system follows this source, an event-scoped organizer may be able to reach form-field create, list, or reorder logic for an unrelated event despite the event access guard sending a denial response.
Source evidence
backend/routes/admin.ts:17installs the top-level admin router guard.backend/middleware/auth.ts:151allowseventAdmininto that router.backend/middleware/auth.ts:181is the unauthorized eventAdmin denial path.backend/routes/admin/eventFormFields.ts:20defines create form-field.backend/routes/admin/eventFormFields.ts:35callsrequireEventAccessmanually inside create.backend/routes/admin/eventFormFields.ts:67reachesprisma.eventFormFields.create.backend/routes/admin/eventFormFields.ts:359defines list form-fields.backend/routes/admin/eventFormFields.ts:375callsrequireEventAccessmanually inside list.backend/routes/admin/eventFormFields.ts:397reachesprisma.eventFormFields.findMany.backend/routes/admin/eventFormFields.ts:431defines reorder form-fields.backend/routes/admin/eventFormFields.ts:446callsrequireEventAccessmanually inside reorder.backend/routes/admin/eventFormFields.ts:490reachesprisma.eventFormFields.update.
Local-only reproduction
I validated the source path using a local static model only:
python3 findings/20260603-1153-hitcon-sitcon-event-form-fields-auth-continues/local-repro.py
The script checks guard placement, the denial response path, missing post-guard reply.sent checks, and subsequent read/write operations. It reports:
{
"observed_candidate_behavior": true,
"network_requests": 0,
"validation_mode": "LOCAL_SOURCE_STATIC_MODEL"
}
Impact
Event form fields define registration form requirements, prompts, options, ordering, and conditional behavior. Cross-event access to this surface could let an event-scoped organizer read another event's form schema/configuration or alter registration form fields for an event they should not manage.
This report is intentionally conservative: I validated public source and local control flow only. I did not prove live production exploitability.
Safety boundary
This report is based on public source and local static validation. I did not log in to SITCON, request SITCON production/private endpoints, create/list/reorder/mutate any real form field, access real registration data, use scanners/fuzzing/DoS, contact SITCON, publish an issue, or open a PR.
修補建議
Use preHandler: requireEventAccess for these routes so Fastify stops the request before the handler body, or immediately return after each manual guard call when reply.sent is true. Prefer the route preHandler style used by neighboring admin routes.