Skip to content

Verified: admin can leak root access token and escalate to Root #2425

Description

@yaowenxiao721

Summary

An authenticated admin can retrieve the root user's reusable management access_token from the admin-only user listing/search APIs and then use that token in the Authorization header to access Root-only endpoints. This creates a practical admin -> root privilege-escalation chain and results in full compromise of Root-only configuration APIs.

Details

The repository defines admin and root as distinct privilege levels:

  • RoleAdminUser = 10
  • RoleRootUser = 100

The Root-only configuration API is explicitly protected with RootAuth():

  • GET /api/option/
  • PUT /api/option/

However, the admin-only user batch APIs return user objects that still include the access_token field:

  • GET /api/user/
  • GET /api/user/search

Relevant code paths:

  • model/user.go
    • User.AccessToken is JSON-serializable
    • GetAllUsers(...) omits password but not access_token
    • SearchUsers(...) omits password but not access_token
  • router/api.go
    • /api/user/ and /api/user/search are protected by AdminAuth()
    • /api/option/ is protected by RootAuth()
  • middleware/auth.go
    • Authorization is accepted as a management access_token
    • once valid, the caller inherits the target user's role and identity

This means an ordinary admin can:

  1. call the admin-only user list/search API
  2. read the root user's access_token from the JSON response
  3. replay that token in Authorization
  4. successfully cross the RootAuth() boundary and invoke Root-only APIs

This appears unintended for two reasons:

  1. the codebase clearly separates admin and root
  2. the single-user read path already contains stronger protection:
    • GetUser(...) blocks admins from reading same-level or higher-privilege users
    • GetUserById(..., false) omits access_token

So the vulnerable behavior is specifically the batch/list/search path leaking a reusable higher-privilege credential.

PoC

Verified locally with Docker on a fresh instance.

Environment

  • Image: justsong/one-api:latest
  • Fresh database
  • Default bootstrap root account present

Steps

  1. Start a fresh instance.

  2. Log in as the default root account:

    • username: root
    • password: 123456
  3. Create a normal user, for example:

    • username: adm1n
    • password: password123
  4. Promote that user to admin.

  5. Log in as adm1n.

  6. Request the admin-only user list:

GET /api/user/
Cookie: <admin session cookie>
  1. Observe that the response includes all listed users' access_token values, including the root user's token. Example response fragment:
{
  "id": 1,
  "username": "root",
  "role": 100,
  "access_token": "<root_access_token>"
}
  1. Control check: try to access the Root-only options API using only the admin session:
GET /api/option/
Cookie: <admin session cookie>

Observed result:

{"message":"无权进行此操作,权限不足","success":false}
  1. Reuse the leaked root token:
GET /api/option/
Authorization: <root_access_token>

Observed result:

  • request succeeds
  • Root-only configuration data is returned

This proves the leaked credential is directly reusable for privilege escalation.

Impact

This is an authenticated privilege-escalation vulnerability affecting any deployment where a user has admin access but should not have root access.

Impact includes:

  • admin -> root privilege escalation
  • unauthorized access to Root-only APIs
  • exposure of sensitive global configuration
  • potential unauthorized modification of system-wide settings
  • compromise of the highest-privilege application account

Suggested CWE mapping:

  • CWE-200 — Exposure of Sensitive Information to an Unauthorized Actor
  • CWE-269 — Improper Privilege Management

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions