# Stocky App Administrator can create a backdoor admin account by using an existing POS User

Stocky's hidden POS-user edit endpoint accepts user[admin]=1, letting an app admin convert a POS user into a persistent backdoor admin account.

- Payout: hidden
- Severity: medium
- Program: Shopify
- Found by: imgnotfound
- Disclosed: 2020-08-24
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/962895
- Library page: https://bugbountylibrary.com/r/h1%3A962895
- Tags: area:web domain:web impact:integrity impact:privesc kind:bounty platform:hackerone sev:medium technique:source-review vuln:access-control vuln:privilege-escalation

**Target:** Stocky web app user management endpoint /users/{id}/edit
**Root cause:** The hidden POS-user edit endpoint lacks UI exposure but still binds the user[admin] parameter server-side, allowing privilege assignment via mass assignment on a user type not meant to be editable.
**Steps:**
1. Create a POS user by opening Stocky from the POS mobile app.
2. As Stocky admin, open /preferences/users and hover the delete button to read the POS user's id.
3. Navigate to `https://stocky.shopifyapps.com/users/{user_id}/edit`.
4. Set the email field to an attacker-controlled address to enable password setup.
5. Intercept the save request and add `user[admin]=1` to the payload.
6. Log in with the POS user's email/password; account now has admin role.
**How found:** Noticed POS users had no edit UI but the delete button leaked their user id, then tried the /users/{id}/edit endpoint and added user[admin] to the save request.
**Exploitation:** An admin (or ex-admin retaining app permission) edits a POS user via the undocumented endpoint, sets their own email, and injects user[admin]=1 to grant admin. The account persists as a backdoor usable after the original admin role is revoked, provided Stocky app permission remains.
**Escalation:** Persistence: backdoor survives revocation of the attacker's own admin role as long as app permission is retained.
**Insight:** When a UI hides edit controls for a record type, the underlying edit endpoint often still exists and binds all model attributes; probe hidden /{id}/edit routes and inject role fields like user[admin] into the save payload.

