Initial commit

This commit is contained in:
Ronald Huynen
2026-03-23 21:37:59 +01:00
commit 2547717edb
2193 changed files with 972171 additions and 0 deletions

View File

@@ -0,0 +1,598 @@
# Admin Management Components Security Analysis
**Date:** 2025-12-31
**Scope:** Posts, Categories, Tags, Profiles, and Mailings Management
**Status:** ⚠️ PARTIAL PROTECTION - CRITICAL VULNERABILITIES FOUND
---
## Executive Summary
**STATUS: ⚠️ SECURITY GAPS IDENTIFIED**
Analysis of 5 admin management Livewire components reveals **significant authorization vulnerabilities**. While some components have basic authentication checks, **NONE of them use ProfileAuthorizationHelper** for IDOR protection, and most lack proper admin permission verification.
**Critical Finding:** Users can potentially access admin management interfaces by manipulating session variables, as authorization is checked inconsistently across components.
---
## Components Analyzed
1. **Posts/Manage.php** - Line 1364 (NO authorization checks)
2. **Categories/Manage.php** - Line 1017 (NO authorization checks)
3. **Tags/Manage.php** - Line 735 (NO authorization checks)
4. **Profiles/Manage.php** - Line 1840 (NO ProfileAuthorizationHelper)
5. **Mailings/Manage.php** - Line 1145 (Basic guard check only)
---
## Security Analysis by Component
### 1. Posts/Manage.php ❌ CRITICAL VULNERABILITY
**File:** `app/Http/Livewire/Posts/Manage.php`
**Lines:** 1-1364
**Authorization Status:** ❌ **NO AUTHORIZATION CHECKS**
**Vulnerabilities:**
- **No mount() authorization** - Anyone can access the component
- **No ProfileAuthorizationHelper** usage
- **No admin permission checks**
- **No guard verification**
**Attack Scenarios:**
```php
// Attack: Regular user accesses admin post management
// 1. User authenticates as regular user on 'web' guard
// 2. User manipulates session to access admin area
// 3. User can view/edit/delete all posts system-wide
// 4. NO PROTECTION - Component allows full access
```
**Exposed Methods (All Unprotected):**
- `edit($translationId)` - Line 301 - Can edit ANY post by ID
- `save()` - Line 409 - Can modify ANY post
- `deleteSelected()` - Line 742 - Can bulk delete posts
- `undeleteSelected()` - Line 773 - Can restore posts
- `stopPublication()` - Line 884 - Can unpublish any post
- `startPublication()` - Line 912 - Can publish any post
**Impact:** CRITICAL - Complete unauthorized access to post management
---
### 2. Categories/Manage.php ❌ CRITICAL VULNERABILITY
**File:** `app/Http/Livewire/Categories/Manage.php`
**Lines:** 1-1017
**Authorization Status:** ❌ **NO AUTHORIZATION CHECKS**
**Vulnerabilities:**
- **No mount() authorization** - Anyone can access
- **No ProfileAuthorizationHelper** usage
- **No admin permission checks**
- **No guard verification**
**Attack Scenarios:**
```php
// Attack: Regular user manages categories
// 1. User accesses category management without admin rights
// 2. Can view all categories and their translations
// 3. Can edit/delete categories (affecting tags system-wide)
// 4. Can create new categories
// 5. NO PROTECTION - Full category system access
```
**Exposed Methods (All Unprotected):**
- `openBulkDeleteTranslationsModal()` - Line 140
- `deleteSelected()` - Line 232 - Deletes categories with tag reassignment
- `deleteCategory()` - Line 418 - Deletes single category
- `updateCategory()` - Line 547 - Modifies categories
- `storeCategory()` - Line 682 - Creates new categories
**Impact:** CRITICAL - Unauthorized category management affects entire tag system
---
### 3. Tags/Manage.php ❌ CRITICAL VULNERABILITY
**File:** `app/Http/Livewire/Tags/Manage.php`
**Lines:** 1-735
**Authorization Status:** ❌ **NO AUTHORIZATION CHECKS**
**Vulnerabilities:**
- **No mount() authorization** - Anyone can access
- **No ProfileAuthorizationHelper** usage
- **No admin permission checks**
- **No guard verification**
**Attack Scenarios:**
```php
// Attack: Regular user manages tags
// 1. User accesses tag management interface
// 2. Can view all tags with user counts
// 3. Can edit tags (affecting all profiles using them)
// 4. Can merge tags (changing profile tags globally)
// 5. Can delete tags (removing skills from profiles)
// 6. NO PROTECTION - Complete tag system access
```
**Exposed Methods (All Unprotected):**
- `openDeleteTagModal($tagId)` - Line 124
- `deleteTag()` - Line 320 - Deletes tags
- `openBulkDeleteTagsModal()` - Line 137
- `deleteSelected()` - Line 353 - Bulk deletes tags
- `openEditTagModal($tagId)` - Line 193
- `updateTag()` - Line 453 - Modifies/merges tags (affects ALL profiles)
**Special Concern - Tag Merging:**
```php
// Line 461-479: Tag merging without authorization
// This affects ALL profiles that have the merged tag
DB::table('taggable_taggables')
->where('tag_id', $this->selectedTagId)
->update(['tag_id' => $mergeTagId]);
```
**Impact:** CRITICAL - Tag modifications affect all user profiles system-wide
---
### 4. Profiles/Manage.php ⚠️ INSUFFICIENT PROTECTION
**File:** `app/Http/Livewire/Profiles/Manage.php`
**Lines:** 1-1840
**Authorization Status:** ⚠️ **BASIC CHECK ONLY - NO IDOR PROTECTION**
**Current Protection (Lines 96-102):**
```php
public function mount()
{
// Check authorization
if (!Auth::guard('admin')->check() && !Auth::guard('bank')->check()) {
abort(403, __('Unauthorized to access mailings management.'));
}
// ... initialization code
}
```
**Vulnerabilities:**
- ✅ Has basic guard check in mount()
- ❌ **No ProfileAuthorizationHelper** usage
- ❌ **No verification** that admin accessing their own admin profile
- ❌ **Allows Bank level=1 to access** (not restricted to level=0 central bank)
**Attack Scenarios:**
```php
// Attack 1: Cross-guard attack (similar to ExportProfileData issue)
// 1. User authenticated on 'web' guard
// 2. User IS a manager of Bank ID 1
// 3. User manipulates session to active Bank profile
// 4. mount() check PASSES (Bank guard exists)
// 5. But user is on WRONG GUARD (web instead of bank)
// 6. Can access profile management as if they were Bank
// Result: Unauthorized access to profile management
// Attack 2: Bank level 1 accessing admin functions
// 1. Bank level 1 authenticates on 'bank' guard
// 2. mount() check PASSES (Bank guard exists)
// 3. Bank level 1 shouldn't have admin access
// Result: Non-central banks can manage all profiles
```
**Exposed Methods (Insufficient Protection):**
- `openEditAccountsModal($profileId, $modelName)` - Line 216
- `openEditProfileModal($profileId, $modelName)` - Line 258
- `updateProfile()` - Line 631 - Can edit ANY profile
- `deleteProfile()` - Line 1386 - Can delete profiles
- `restoreProfile()` - Line 1493 - Can restore deleted profiles
**Missing Validation:**
- No check that admin is acting on behalf of their own Admin profile
- No verification of cross-guard attacks
- No restriction for Bank level (should be level=0 only)
**Impact:** HIGH - Partial protection but vulnerable to guard manipulation
---
### 5. Mailings/Manage.php ⚠️ INSUFFICIENT PROTECTION
**File:** `app/Http/Livewire/Mailings/Manage.php`
**Lines:** 1-1145
**Authorization Status:** ⚠️ **BASIC CHECK ONLY - NO IDOR PROTECTION**
**Current Protection (Lines 96-102):**
```php
public function mount()
{
// Check authorization
if (!Auth::guard('admin')->check() && !Auth::guard('bank')->check()) {
abort(403, __('Unauthorized to access mailings management.'));
}
$this->estimatedRecipientCount = 0;
}
```
**Vulnerabilities:**
- ✅ Has basic guard check in mount()
- ❌ **No ProfileAuthorizationHelper** usage
- ❌ **No verification** of cross-guard attacks
- ❌ **Allows Bank access** without level verification
**Attack Scenarios:**
```php
// Attack: Cross-guard mailing access
// 1. User authenticated on 'web' guard
// 2. User is manager of Bank ID 1
// 3. User manipulates session: activeProfileType = Bank, activeProfileId = 1
// 4. mount() check PASSES because Bank guard exists
// 5. User on WRONG GUARD accesses mailing management
// Result: Unauthorized mailing access
```
**Exposed Methods (Insufficient Protection):**
- `openCreateModal()` - Line 163
- `openEditModal($mailingId)` - Line 170
- `saveMailing()` - Line 418 - Creates/updates mailings
- `deleteMailing($mailingId)` - Line 485
- `sendMailing()` - Line 527 - Sends emails to users
- `sendTestMail($mailingId)` - Line 611
**Missing Validation:**
- No cross-guard attack prevention
- No admin profile ownership verification
- Bank access not restricted to central bank only
**Impact:** HIGH - Can create/send mass mailings without proper authorization
---
## Common Vulnerabilities Across All Components
### 1. Missing ProfileAuthorizationHelper Integration
**Issue:** None of the 5 components use ProfileAuthorizationHelper
**Impact:** No IDOR protection, no cross-guard validation
### 2. Inconsistent Authorization Checks
**Issue:** Only 2/5 components have ANY authorization (Profiles and Mailings)
**Impact:** 3 components (Posts, Categories, Tags) are completely unprotected
### 3. No Active Profile Verification
**Issue:** Components don't verify that active profile matches authenticated profile
**Impact:** Cross-guard attacks possible (similar to ExportProfileData vulnerability)
### 4. Bank Level Not Validated
**Issue:** Bank level 1 can access admin functions
**Impact:** Non-central banks have admin privileges
---
## Recommended Security Fixes
### Priority 1: CRITICAL (Posts, Categories, Tags)
**Add ProfileAuthorizationHelper to mount():**
```php
public function mount()
{
// Get active profile from session
$activeProfileType = session('activeProfileType');
$activeProfileId = session('activeProfileId');
if (!$activeProfileType || !$activeProfileId) {
abort(403, __('No active profile selected'));
}
$profile = $activeProfileType::find($activeProfileId);
if (!$profile) {
abort(403, __('Active profile not found'));
}
// Validate profile ownership using ProfileAuthorizationHelper
\App\Helpers\ProfileAuthorizationHelper::authorize($profile);
// Verify admin permissions
if (!($profile instanceof \App\Models\Admin)) {
abort(403, __('Admin access required'));
}
// Additional initialization...
}
```
### Priority 2: HIGH (Profiles, Mailings)
**Enhance existing mount() with ProfileAuthorizationHelper:**
```php
public function mount()
{
// Get active profile
$activeProfileType = session('activeProfileType');
$activeProfileId = session('activeProfileId');
if (!$activeProfileType || !$activeProfileId) {
abort(403, __('No active profile selected'));
}
$profile = $activeProfileType::find($activeProfileId);
if (!$profile) {
abort(403, __('Active profile not found'));
}
// Use ProfileAuthorizationHelper for cross-guard protection
\App\Helpers\ProfileAuthorizationHelper::authorize($profile);
// Verify admin or central bank access
if ($profile instanceof \App\Models\Admin) {
// Admin access OK
} elseif ($profile instanceof \App\Models\Bank) {
// Only central bank (level 0)
if ($profile->level !== 0) {
abort(403, __('Central bank access required'));
}
} else {
abort(403, __('Admin or central bank access required'));
}
// Continue with initialization...
}
```
### Additional Protection: Route Middleware
**Create Admin Authorization Middleware:**
```php
// app/Http/Middleware/RequireAdminProfile.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use App\Helpers\ProfileAuthorizationHelper;
class RequireAdminProfile
{
public function handle(Request $request, Closure $next)
{
$activeProfileType = session('activeProfileType');
$activeProfileId = session('activeProfileId');
if (!$activeProfileType || !$activeProfileId) {
abort(403, __('No active profile selected'));
}
$profile = $activeProfileType::find($activeProfileId);
if (!$profile) {
abort(403, __('Active profile not found'));
}
// Use ProfileAuthorizationHelper
ProfileAuthorizationHelper::authorize($profile);
// Verify admin or central bank
if ($profile instanceof \App\Models\Admin) {
return $next($request);
}
if ($profile instanceof \App\Models\Bank && $profile->level === 0) {
return $next($request);
}
abort(403, __('Admin or central bank access required'));
}
}
```
**Apply to routes:**
```php
// routes/web.php
Route::middleware(['auth', 'admin-profile'])->group(function () {
Route::get('/posts/manage', \App\Http\Livewire\Posts\Manage::class);
Route::get('/categories/manage', \App\Http\Livewire\Categories\Manage::class);
Route::get('/tags/manage', \App\Http\Livewire\Tags\Manage::class);
Route::get('/profiles/manage', \App\Http\Livewire\Profiles\Manage::class);
Route::get('/mailings/manage', \App\Http\Livewire\Mailings\Manage::class);
});
```
---
## Test Coverage Recommendations
### Posts Management Authorization Tests
```php
// tests/Feature/Security/Authorization/PostsManageAuthorizationTest.php
/** @test */
public function admin_can_access_posts_management()
{
$admin = Admin::factory()->create();
$this->actingAs($admin, 'admin');
session(['activeProfileType' => Admin::class, 'activeProfileId' => $admin->id]);
$response = Livewire::test(\App\Http\Livewire\Posts\Manage::class);
$response->assertStatus(200);
}
/** @test */
public function user_cannot_access_posts_management()
{
$user = User::factory()->create();
$this->actingAs($user, 'web');
session(['activeProfileType' => User::class, 'activeProfileId' => $user->id]);
$response = Livewire::test(\App\Http\Livewire\Posts\Manage::class);
$response->assertStatus(403);
}
/** @test */
public function web_user_cannot_access_admin_posts_via_cross_guard_attack()
{
$user = User::factory()->create();
$admin = Admin::factory()->create();
$admin->users()->attach($user->id); // User is linked to admin
// User authenticated on 'web' guard
$this->actingAs($user, 'web');
// Malicious: manipulate session to target admin profile
session(['activeProfileType' => Admin::class, 'activeProfileId' => $admin->id]);
$response = Livewire::test(\App\Http\Livewire\Posts\Manage::class);
$response->assertStatus(403); // Should be blocked by ProfileAuthorizationHelper
}
/** @test */
public function admin_cannot_edit_post_without_proper_authorization()
{
$admin1 = Admin::factory()->create();
$admin2 = Admin::factory()->create();
$post = Post::factory()->create();
$translation = $post->translations()->first();
$this->actingAs($admin1, 'admin');
session(['activeProfileType' => Admin::class, 'activeProfileId' => $admin1->id]);
// Attempt to manipulate session to access as different admin
session(['activeProfileId' => $admin2->id]);
$response = Livewire::test(\App\Http\Livewire\Posts\Manage::class)
->call('edit', $translation->id);
$response->assertStatus(403);
}
```
### Similar tests needed for:
- Categories Management (30+ tests)
- Tags Management (30+ tests)
- Profiles Management (40+ tests)
- Mailings Management (25+ tests)
**Total Recommended Tests:** ~150 authorization tests across 5 components
---
## Security Logging Recommendations
**Add logging to all admin operations:**
```php
// In mount() after authorization
Log::info('Admin management access', [
'component' => get_class($this),
'admin_id' => $profile->id,
'admin_type' => get_class($profile),
'authenticated_guard' => Auth::getDefaultDriver(),
'ip_address' => request()->ip(),
]);
// In sensitive operations (delete, update, etc.)
Log::warning('Admin operation performed', [
'operation' => 'delete_post',
'admin_id' => $profile->id,
'target_id' => $postId,
'ip_address' => request()->ip(),
]);
```
---
## Attack Surface Summary
| Component | Current Status | Attack Vectors | Impact Level |
|-----------|---------------|----------------|--------------|
| Posts/Manage | ❌ No protection | Session manipulation, Direct access | CRITICAL |
| Categories/Manage | ❌ No protection | Session manipulation, Direct access | CRITICAL |
| Tags/Manage | ❌ No protection | Session manipulation, Direct access | CRITICAL |
| Profiles/Manage | ⚠️ Basic check | Cross-guard attack, Bank level bypass | HIGH |
| Mailings/Manage | ⚠️ Basic check | Cross-guard attack, Bank level bypass | HIGH |
---
## Compliance Impact
### OWASP Top 10 2021
❌ **A01:2021 Broken Access Control**
- Admin interfaces lack proper authorization
- Cross-guard attacks possible
- No IDOR protection on management endpoints
### CWE Coverage
❌ **CWE-639: Authorization Bypass Through User-Controlled Key**
- Session manipulation allows unauthorized access
❌ **CWE-284: Improper Access Control**
- Missing admin permission verification
- No cross-guard validation
### GDPR Compliance
⚠️ **Data Protection (Article 32)**
- Admin access to all user data not properly secured
- No audit trail for admin actions
---
## Production Deployment Blockers
**DO NOT DEPLOY TO PRODUCTION until:**
- [ ] Posts/Manage.php has ProfileAuthorizationHelper integration
- [ ] Categories/Manage.php has ProfileAuthorizationHelper integration
- [ ] Tags/Manage.php has ProfileAuthorizationHelper integration
- [ ] Profiles/Manage.php enhanced with ProfileAuthorizationHelper
- [ ] Mailings/Manage.php enhanced with ProfileAuthorizationHelper
- [ ] Admin authorization middleware created and applied
- [ ] ~150 authorization tests written and passing
- [ ] Security audit conducted on all admin endpoints
- [ ] Monitoring configured for admin access attempts
---
## Conclusion
**CRITICAL SECURITY GAPS IDENTIFIED:**
5 admin management components analyzed:
- ❌ 3 components (Posts, Categories, Tags) have **ZERO authorization protection**
- ⚠️ 2 components (Profiles, Mailings) have **insufficient protection**
- ❌ 0 components use ProfileAuthorizationHelper
- ❌ No cross-guard attack prevention
- ❌ No comprehensive authorization testing
**The admin management system is NOT PRODUCTION READY from a security perspective.**
**Immediate Actions Required:**
1. Integrate ProfileAuthorizationHelper into all 5 components
2. Add admin permission verification
3. Implement cross-guard attack prevention
4. Create comprehensive test suite (~150 tests)
5. Add security logging for all admin operations
6. Security team review before production deployment
---
**Document Version:** 1.0
**Last Updated:** 2025-12-31
**Prepared By:** Claude Code Security Audit
**Status:** ❌ CRITICAL VULNERABILITIES FOUND - NOT PRODUCTION READY