fluentcms / fluentcms/FluentCMS
Cross-tenant authorization bypass in PermissionManager and File/Folder services
- Dominant language
- C#
- Stars
- 565
- Forks
- 107
- PR merge metrics
- No merged PRs in 30d
Description
### Summary
FluentCMS does not consistently bind authorization decisions to the site that owns the requested object. An authenticated administrator restricted to Site A can enumerate Site B and, when a Site B folder UUID is supplied to File Management, read and modify Site B assets.
Tested on official tag `v0.0.5`. The same vulnerable code is present at `dev` commit `c63d49cdbc1f4051d34bb71087d904c56e33951e`.
### Root cause
In `PermissionManager.HasAccess(Guid siteId, ...)`, authorization collections are populated once and then reused for later site IDs:
```csharp
_userRoles ??= (await _userRoleRepository.GetUserRoles(_apiExecutionContext.UserId, siteId, cancellationToken))
.Where(ur => ur.SiteId == siteId).ToList();
_roles ??= (await _roleRepository.GetAllForSite(siteId, cancellationToken)).ToList();
_permissions ??= (await _permissionRepository.GetAllForSite(siteId, cancellationToken)).ToList();
```
`GetAccessible` calls `HasAccess` repeatedly for different sites, so roles loaded for the first site can be reused when evaluating subsequent sites.
Additionally, `FolderService.GetAll/GetById` and `FileService.Create/GetById` access objects by UUID without checking `IPermissionManager.HasAccess` for the owning `SiteId`.
Affected source:
- https://github.com/fluentcms/FluentCMS/blob/c63d49cdbc1f4051d34bb71087d904c56e33951e/src/Backend/FluentCMS.Services/Permissions/PermissionManager.cs
- https://github.com/fluentcms/FluentCMS/blob/c63d49cdbc1f4051d34bb71087d904c56e33951e/src/Backend/FluentCMS.Services/FolderService.cs
- https://github.com/fluentcms/FluentCMS/blob/c63d49cdbc1f4051d34bb71087d904c56e33951e/src/Backend/FluentCMS.Services/FileService.cs
### Proof of concept
1. Create Site A and Site B.
2. Assign a test account to the `Administrators` role of Site A only. Do not assign any Site B role.
3. Authenticate as that Site A-only administrator.
4. Open `/admin/sites`.
5. Observe that Site B and its ID are returned to the Site A-only administrator.
6. Supply a Site B folder UUID to `/admin/files?folderId=`.
7. Observe that Site B filenames and download paths are rendered.
8. Upload a benign text file through File Management while the Site B folder is selected.
9. Observe that the created object belongs to Site B but its `createdBy` field is the Site A-only administrator.
Laboratory assertions:
```text
GET /admin/files?folderId=
Status: 200
Authenticated as Site A-only administrator: true
Site B filename disclosed: true
Site B download link disclosed: true
Cross-site upload response:
siteId:
folderId:
createdBy:
isSuccess: true
```
### Impact
A site administrator may enumerate sites outside their assigned scope and, with a referenced object UUID, read, upload, rename, move, or delete assets belonging to another site. This violates tenant isolation and can affect confidentiality, integrity, and availability in multi-site deployments.
### Severity
- High
- CVSS 3.1: `CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H` (7.2)
- CWE-862: Missing Authorization
- CWE-639: Authorization Bypass Through User-Controlled Key
### Suggested remediation
- Key cached authorization data by `siteId`, or reload it for every site evaluation.
- Add explicit per-site authorization checks to every File and Folder read/write operation.
- Add two-site integration tests verifying that a Site A administrator cannot enumerate or mutate Site B objects.
I am available to provide additional reproduction details and validate a patch.
Contributor guide
Research direction
Start with PermissionManager.HasAccess and GetAccessible, then inspect FolderService.GetAll/GetById and FileService.Create/GetById at the referenced commit. Trace how site IDs and object UUIDs reach authorization decisions. Done means two-site integration tests show a Site A administrator cannot enumerate or read or mutate Site B folders and files.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- authorization, backend, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100