Tenant Administrator Can Mutate Platform-Global Configuration via /param/submit
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(id1123598819738675202) had its shipped value123456.
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:
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:
{"code":200,"success":true,"msg":"操作成功"}The persistent state changed as follows:
blade_param(account.initPassword).param_value: 123456 -> PwnedByTenantBExpected 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.
Source: chillzhuang/SpringBlade