$ cat writeup.md…
$ cat writeup.md…
avitoctf
Task: A government portal exposed signed documents, a HoneyOffice API, and an Intercom support widget without verified identities. Solution: Impersonate the Queen by email, recover her administrator API key from support history, and delete the decree.
Парламент расширил полномочия пограничной службы, а Королева объявила медоедов недружественным видом. Требовалось незаметно удалить королевский указ.
The target was a React government portal. The objective was to delete the Queen's decree, but an ordinary citizen session did not have sufficient permission to call the document deletion API.
The React bundle and /honeyoffice-openapi.yaml exposed the relevant HoneyOffice surface:
1;GET /api/documents/1/archive for a verification archive;DELETE /api/documents/1 for deletion;hof365_.The changelog explained that support agents issue HoneyOffice keys through chat. The frontend initialized Intercom application r84vggjn with the logged-in email, but did not supply a server-generated Intercom Identity Verification user_hash. Consequently, the browser—not the application server—asserted which portal user was opening Messenger.
The public archive contained only the decree PDF, its detached signature, and the Queen's public PGP key. It contained no private key or hidden credential. Nevertheless, the public key provided the identity needed for the chat attack:
unzip -l decree.zip unzip -p decree.zip queen-public-key.asc > queen-public-key.asc gpg --show-keys --with-colons queen-public-key.asc
The output disclosed the UID Queen <[email protected]> and fingerprint 6F7AAEBFED593D02875485043089457CA0DEF0BC. The fingerprint also matched the metadata returned by /api/documents.
Missing Intercom Identity Verification allowed an attacker to submit any victim email to Messenger and inherit that person's support identity and history. The signed public document supplied the privileged Queen's email, turning the identity-verification failure into administrator API-key disclosure.
The third-party Intercom endpoint was tested only after explicit scope authorization covered the discovered Intercom origins.
The request below reproduces the identity assertion. It sends the public Intercom app ID and the Queen's public email without a user_hash:
curl 'https://api-iam.intercom.io/messenger/web/open' \ -X POST \ -H 'Origin: https://government-n22ocjrj.avitoctf.ru' \ -H 'Referer: https://government-n22ocjrj.avitoctf.ru/' \ -H 'X-INTERCOM-APP: r84vggjn' \ -H 'X-INTERCOM-USER-DATA: {"app_id":"r84vggjn","email":"[email protected]"}' \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data 'app_id=r84vggjn&email=queen%40hive.gov&platform=web&installation_type=npm-package' \ -o intercom-open.json
Intercom accepted the email-only identity and identified the widget user as the Queen of the Hive. The returned recent conversation titled “API token” included Fin's reply containing an administrator HoneyOffice key. Its concrete value is intentionally omitted and represented as hof365_REDACTED.
Use the recovered key as the HoneyOffice bearer credential:
curl 'https://government-n22ocjrj.avitoctf.ru/api/documents/1' \ -X DELETE \ -H 'Authorization: Bearer hof365_REDACTED' \ -H 'Content-Type: application/json' \ --data '{"id":1}'
The endpoint returned HTTP 202, status deleted, and the challenge flag in its message.
sess_ token reached the deletion endpoint but received HTTP 403 with an “insufficient privileges” error.role, is_admin, and nested variants still created citizen accounts./api/support/api-keys returned 401 anonymously and 403 as a citizen before body parsing. BOLA, parser, spoofed-header, query, and method-override variants did not bypass authorization.user_hash only on the trusted application server.The solve was verified against notes.md, app.js, honeyoffice-openapi.yaml, documents.json, decree.zip, intercom-open2.json, delete-admin.json, and the corresponding response-header captures in the task directory.
$ cat /etc/motd
Liked this one?
Pro unlocks every writeup, every flag, and API access. $9/mo.
$ cat pricing.md$ grep --similar