-
Notifications
You must be signed in to change notification settings - Fork 292
Description
Summary
8 authorization bypass vulnerabilities were identified. The root cause is that SecureAJAXInterface only validates authentication (login status) but NOT authorization (access level). Multiple AJAX endpoints were shipped without per-endpoint access level checks.
Findings
1. deleteActivity.php (HIGH) - Any READ-level user can delete activity records
Line 33-47: Only checks SecureAJAXInterface (login). setCandidateJobOrderRating.php correctly checks ACCESS_LEVEL_EDIT.
2. editActivity.php (HIGH) - Any READ-level user can modify activity records
Line 36-117: Same pattern. No access level check before $activityEntries->update().
3. testEmailSettings.php (HIGH) - Email relay via any authenticated user
Line 33-114: Sends email with user-controlled from/to addresses. Settings module requires ACCESS_LEVEL_SA for email settings (SettingsUI.php:492).
4. Saved List CRUD (MEDIUM) - 4 list AJAX endpoints missing access checks
modules/lists/ajax/deleteList.php, editListName.php, newList.php, addToLists.php: No access level checks. Any READ user can create/rename/delete saved lists.
5. Import revert (HIGH) - Undo data imports without EDIT access
modules/import/ImportUI.php:64-164: revert action has no access check. import action correctly checks ACCESS_LEVEL_EDIT (line 411).
6. Reports module (MEDIUM) - All reports accessible to any user including EEO data
modules/reports/ReportsUI.php:51-91: Zero access checks. EEO demographic reports (ethnicity, gender, disability) accessible to READ-level users.
7. getLicenseKey (MEDIUM) - No authentication required
modules/toolbar/ToolbarUI.php:46,282: _authenticationRequired = false. License key returned to unauthenticated users.
8. Calendar edit/delete (MEDIUM) - No ownership check
modules/calendar/CalendarUI.php:505,693: Checks access level but not event ownership. Any user at EDIT/DELETE level can modify/delete other users' events.
Root Cause
SecureAJAXInterface validates authentication only, not authorization. Each AJAX endpoint is responsible for its own access level check, creating inconsistency.
Suggested Fix
Add access level checks to SecureAJAXInterface or create a new SecureAuthorizedAJAXInterface that accepts a required access level parameter.