Vulnerability Detail Report
Vulnerability Overview
- ZDID: ZD-2026-00809
- Vendor: SITCON 學生計算機年會
- Title: SITCON 學生計算機年會 tickets invitation-code update can rebind a code to another event ticket
- Introduction: The public SITCON tickets invitation-code update route authorizes the current code event but can write a new ticketId from another event without authorizing that target event.
處理狀態
目前狀態
-
新提交
-
已審核
-
已通報
-
已修補
-
未複測
-
公開
處理歷程
- 2026/06/03 19:50:03 : 新提交 (由 老狼 更新此狀態)
- 2026/06/10 12:49:00 : 審核中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2026/09/18 15:33:06 : 已修補 (由 組織帳號 更新此狀態)
- 2026/09/19 03:00:13 : 公開 (由 HITCON ZeroDay 平台自動更新)
詳細資料
- ZDID:ZD-2026-00809
- 通報者: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/invitationCodes.ts
https://github.com/sitcon-tw/tickets/blob/db4a3500c0331bdc5c204808399c52aa024b87e8/backend/middleware/auth.ts
https://github.com/sitcon-tw/tickets/blob/db4a3500c0331bdc5c204808399c52aa024b87e8/types/src/invitation.ts
敘述
Summary
The public sitcon-tw/tickets backend has an admin invitation-code update route:
PUT /api/admin/invitation-codes/:id
The route uses requireEventAccessViaCodeId. That middleware loads the invitation code referenced by :id, reads the current ticket's event ID, and authorizes the eventAdmin against that current event.
However, the update body schema allows ticketId, and the handler writes the new ticketId after only checking that the target ticket exists. It does not verify that the target ticket belongs to an event the eventAdmin can manage.
A local source model therefore shows this mismatch:
existing code-owned -> ticket-owned -> owned-event
body.ticketId = ticket-victim -> victim-event
eventAdmin permissions = [owned-event]
guard authorizes owned-event
handler writes ticket-victim
If deployed as reviewed, an event-scoped organizer may be able to move an invitation code into another event's ticket.
Source evidence
backend/middleware/auth.ts:requireEventAccessViaCodeIdauthorizes using the current code's ticket event.backend/middleware/auth.ts:checkEventAccessauthorizes eventAdmin users withquery.eventId || params.id || body.eventId.types/src/invitation.ts:InvitationCodeUpdateRequestSchemaincludes optionalticketId.backend/schemas.ts:invitationCodeSchemas.updateInvitationCodeuses that update body schema.backend/routes/admin/invitationCodes.ts: the update route usespreHandler: requireEventAccessViaCodeId.backend/routes/admin/invitationCodes.ts: the handler readsticketIdfrom the body, checks only that the target ticket exists, then setsupdatePayload.ticketId = ticketId.
Local-only reproduction
I validated the control flow using local static modeling only:
python3 findings/20260603-1453-hitcon-sitcon-invitation-code-ticketid-rebind/local-repro.py
Result:
{
"observed_candidate_behavior": true,
"network_requests": 0,
"validation_mode": "LOCAL_SOURCE_STATIC_MODEL"
}
Impact
Invitation codes are used to restrict ticket registration flows. Rebinding an invitation code from an authorized event's ticket to another event's ticket can weaken invite-only registration controls and allow an event-scoped organizer to affect ticket access for an event outside their assigned permission set.
This report is intentionally conservative: I validated public source and local control flow only. I did not prove live SITCON production exploitability.
Safety boundary
This report is based on public source and local-only analysis. I did not log in to SITCON, request SITCON production/private endpoints, use a real event ID/ticket ID/invitation code/registration/email, create/move/validate/send/redeem a real invitation code, access real event/ticket/registration/email/form data, use scanners/fuzzing/DoS, contact SITCON, publish an issue, or open a PR.
修補建議
When ticketId is supplied in the update body, load the target ticket and authorize the target ticket eventId before writing it. If invitation codes should not move across tickets, remove ticketId from the update body schema. The event used for authorization should match the event affected by the mutation.