Tenant Administrator Can Mutate Platform-Global Configuration via /param/submit

Author: czTangtCreated Sep 16, 2026Updated Sep 16, 2026

Summary

In SpringBlade, the global parameter endpoint POST /param/submit is guarded only by a role check that every tenant administrator satisfies. The parameter table is platform-global, and the update performs no tenant validation. A tenant administrator can therefore modify or delete platform-global parameter records outside the administrator's own tenant boundary.

Details

SpringBlade's role expression HAS_ROLE_ADMIN matches the role aliases administrator and admin. Tenant provisioning creates a role with alias admin for every new tenant, so every tenant administrator passes this check. The stricter platform-only expression HAS_ROLE_ADMINISTRATOR exists in the same codebase and is used, for example, on tenant creation — but not on the parameter controller.

blade_param is a global table without tenant scoping, and saveOrUpdate writes the submitted row by primary key with no ownership or tenant guard. The shipped database contains global records such as account.initPassword, making the unauthorized cross-tenant write easy to demonstrate. In the stock v5.0.1 code, however, the user-creation, password-reset, user-import, and tenant-provisioning flows do not read this value.

PoC

Tested on SpringBlade v5.0.1 at commit 0c180b9d0d68542ab4a2938e23989db7078832ca (open-source Cloud edition), with the blade-system service running in its documented standalone configuration.

Test conditions:

  • the attacker was the administrator of a separately provisioned tenant (created through the real tenant-creation API), authenticating with that tenant's own admin account;
  • the global parameter account.initPassword (id 1123598819738675202) had its shipped value 123456.

Controls: the same tenant-administrator token was rejected by POST /tenant/submit with 请求未授权 (that endpoint requires the platform administrator), and a plain user token was rejected by GET /tenant/list with the same error. This confirms the token's role claim passes HAS_ROLE_ADMIN but not the platform-administrator check.

The attacker sent:

http
POST /param/submit HTTP/1.1
Host: <TARGET>
blade-auth: bearer <TENANT_ADMIN_JWT>
Content-Type: application/json

{"id":"1123598819738675202","paramName":"账号初始密码","paramKey":"account.initPassword","paramValue":"PwnedByTenantB","status":1}

Observed response:

json
{"code":200,"success":true,"msg":"操作成功"}

The persistent state changed as follows:

blade_param(account.initPassword).param_value: 123456 -> PwnedByTenantB

Expected behavior: platform-global configuration should be modifiable only by the platform administrator. A tenant administrator's request should be rejected without any change.

Impact

Every tenant administrator can modify or delete records in the platform-global blade_param table despite having administrative authority only within their own tenant. This violates the tenant isolation boundary and may affect platform components or custom extensions that consume these shared parameters.

The stock SpringBlade v5.0.1 code does not use account.initPassword when creating accounts, so this report does not claim cross-tenant account takeover. Other HAS_ROLE_ADMIN-protected controllers that operate on non-tenant-scoped tables should also be audited.

Suggested remediation

Protect platform-global configuration endpoints with the platform-administrator check (HAS_ROLE_ADMINISTRATOR) or an equivalent service-layer guard, and audit the remaining HAS_ROLE_ADMIN-only endpoints that write global tables.