# Security Testing Guide This guide provides step-by-step instructions for performing the manual security tests from `references/MANUAL_SECURITY_TESTING_CHECKLIST.md`. ## Prerequisites - You are logged in as **User A (ID: 5195)** - **User B (ID: 5196)** exists as the victim account - **Organization A** and **Organization B** exist - **Bank A** exists (optional) ## Test Accounts | Profile | ID | Email | |---------|-------|-------| | User A (you) | 5195 | user-a@test.nl | | User B (victim) | 5196 | user-b@test.nl | | Organization A | TBD | TBD | | Organization B | TBD | TBD | ## How to Manipulate Session Since Laravel stores sessions server-side (not in browser Session Storage), use this command: ```bash cd /home/r/Websites/timebank_cc_2 php manipulate-session.php ``` **Examples:** ```bash # Change to User B php manipulate-session.php 5196 user # Change to Organization A (ID 1) php manipulate-session.php 1 org # Change to Bank A (ID 1) php manipulate-session.php 1 bank # Change back to User A php manipulate-session.php 5195 user ``` After running the command, **refresh your browser** to apply the changes. --- ## Test Category 1: Profile Deletion Authorization ### Test 1.1: Unauthorized User Profile Deletion **Risk Level:** CRITICAL **Steps:** 1. Login as User A (already done) 2. Note User A's profile ID: **5195** 3. Run session manipulation: ```bash php manipulate-session.php 5196 user ``` 4. Refresh browser 5. Navigate to Settings → Delete Account 6. Attempt to delete the profile **Expected Result:** ✅ HTTP 403 Forbidden error **Security Failure:** ❌ Profile deletion succeeds **Log Verification:** ```bash tail -f storage/logs/laravel.log | grep "ProfileAuthorizationHelper" ``` Should show: "Unauthorized User access attempt" **Reset Session After Test:** ```bash php manipulate-session.php 5195 user # Change back to User A ``` --- ### Test 1.2: Unauthorized Organization Profile Deletion **Risk Level:** CRITICAL **Prerequisites:** Find Organization A and B IDs first: ```bash mysql -u timebank_cc_dev -p'zea2A8sd{QA,9^pS*2^@Xcltuk.vgV' timebank_cc_2 -e \ "SELECT id, name, email FROM organizations WHERE name LIKE '%Organization%' LIMIT 5;" ``` **Steps:** 1. Login as User A (member of Organization A) 2. Switch to Organization A profile using the profile switcher 3. Note Organization A's ID 4. Run session manipulation: ```bash php manipulate-session.php org ``` 5. Refresh browser 6. Navigate to organization settings → Delete Account 7. Attempt deletion **Expected Result:** ✅ HTTP 403 Forbidden **Security Failure:** ❌ Organization B deleted **Reset:** ```bash php manipulate-session.php 5195 user ``` --- ### Test 1.3: Legitimate Profile Deletion (Control Test) **Purpose:** Verify legitimate operations still work **Steps:** 1. Login as User A 2. Ensure session is NOT manipulated (reset if needed): ```bash php manipulate-session.php 5195 user ``` 3. Refresh browser 4. Navigate to Settings → Delete Account 5. Complete deletion process (⚠️ Use a test account, not your main account!) **Expected Result:** ✅ Profile deletion succeeds **Security Failure:** ❌ Legitimate deletion blocked --- ## Test Category 2: Profile Modification Authorization ### Test 2.1: Unauthorized Profile Settings Modification **Risk Level:** CRITICAL **Steps:** 1. Login as User A 2. Navigate to profile settings page 3. Run session manipulation: ```bash php manipulate-session.php 5196 user ``` 4. Refresh browser 5. Attempt to modify profile details (name, email, about, etc.) 6. Click Save **Expected Result:** ✅ HTTP 403 Forbidden **Security Failure:** ❌ User B's profile modified **Reset:** ```bash php manipulate-session.php 5195 user ``` --- ### Test 2.2: Unauthorized Organization Settings Modification **Risk Level:** CRITICAL **Steps:** 1. Login as User A 2. Switch to Organization A 3. Run session manipulation: ```bash php manipulate-session.php org ``` 4. Refresh browser 5. Navigate to organization settings 6. Attempt to modify organization details 7. Click Save **Expected Result:** ✅ HTTP 403 Forbidden **Security Failure:** ❌ Organization B modified **Reset:** ```bash php manipulate-session.php 5195 user ``` --- ## Test Category 3: Message Settings Authorization ### Test 3.1: Unauthorized Message Settings Access **Risk Level:** CRITICAL **Steps:** 1. Login as User A 2. Navigate to Settings → Message Settings 3. Note current notification preferences 4. Run session manipulation: ```bash php manipulate-session.php 5196 user ``` 5. Refresh browser 6. Toggle notification settings (email, push, etc.) 7. Click Save **Expected Result:** ✅ HTTP 403 Forbidden **Security Failure:** ❌ User B's message settings changed **Reset:** ```bash php manipulate-session.php 5195 user ``` --- ## Test Category 4: Chat/Conversation Authorization ### Test 4.1: Unauthorized Conversation Access **Risk Level:** HIGH **Prerequisites:** 1. Create a conversation between User B and another user 2. Note the conversation ID from the URL **Steps:** 1. Login as User A 2. Manually navigate to: `/chat/{conversation_id}` 3. Attempt to view conversation 4. Attempt to send messages **Expected Result:** ✅ HTTP 403 Forbidden or redirect **Security Failure:** ❌ User A can read/send messages --- ## Test Category 5: Transaction/Payment Authorization ### Test 5.1: Unauthorized Transaction Viewing **Risk Level:** HIGH **Prerequisites:** 1. User B creates transaction with User C 2. Note transaction ID **Steps:** 1. Login as User A 2. Navigate to `/transaction/{transaction_id}` **Expected Result:** ✅ HTTP 403 Forbidden **Security Failure:** ❌ User A can view transaction --- ### Test 5.2: Session Manipulation for Transaction Access **Risk Level:** CRITICAL **Steps:** 1. Login as User A 2. Run session manipulation: ```bash php manipulate-session.php 5196 user ``` 3. Refresh browser 4. Navigate to Transactions page 5. Check which transactions are visible **Expected Result:** ✅ Only User A's transactions visible (or 403 error) **Security Failure:** ❌ User B's transactions visible **Reset:** ```bash php manipulate-session.php 5195 user ``` --- ## Useful Commands ### View Current Sessions ```bash mysql -u timebank_cc_dev -p'zea2A8sd{QA,9^pS*2^@Xcltuk.vgV' timebank_cc_2 -e \ "SELECT id, user_id, ip_address, FROM_UNIXTIME(last_activity) as last_active \ FROM sessions WHERE last_activity > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 2 HOUR)) \ ORDER BY last_activity DESC LIMIT 5;" ``` ### Find Profile IDs ```bash # Users mysql -u timebank_cc_dev -p'zea2A8sd{QA,9^pS*2^@Xcltuk.vgV' timebank_cc_2 -e \ "SELECT id, name, email FROM users WHERE name LIKE '%User%' ORDER BY id LIMIT 10;" # Organizations mysql -u timebank_cc_dev -p'zea2A8sd{QA,9^pS*2^@Xcltuk.vgV' timebank_cc_2 -e \ "SELECT id, name, email FROM organizations WHERE name LIKE '%Organization%' LIMIT 10;" # Banks mysql -u timebank_cc_dev -p'zea2A8sd{QA,9^pS*2^@Xcltuk.vgV' timebank_cc_2 -e \ "SELECT id, name, email FROM banks LIMIT 10;" ``` ### Monitor Authorization Logs ```bash # Watch for authorization attempts tail -f storage/logs/laravel.log | grep "ProfileAuthorizationHelper" # Watch for unauthorized access attempts tail -f storage/logs/laravel.log | grep -i "Unauthorized.*access attempt" ``` ### Reset Session to User A ```bash php manipulate-session.php 5195 user ``` --- ## Troubleshooting **Problem:** Session manipulation doesn't work **Solution:** Make sure you refresh the browser after running the command **Problem:** Can't find profile IDs **Solution:** Use the MySQL commands above to query the database **Problem:** Script permission denied **Solution:** Run `chmod +x manipulate-session.php` **Problem:** Need to restore your original session **Solution:** Run `php manipulate-session.php 5195 user` and refresh browser --- ## Important Notes 1. **Always refresh your browser** after manipulating the session 2. **Reset your session** back to User A after each test: `php manipulate-session.php 5195 user` 3. **Monitor logs** during testing: `tail -f storage/logs/laravel.log | grep ProfileAuthorizationHelper` 4. **Don't delete important accounts** - use test accounts for deletion tests 5. These tests are for **security testing only** - never use in production --- ## Test Category 6: AccountInfoModal — IDOR (Balance Leakage) ### Test 6.1: Unauthorized Balance Viewing via Session Manipulation **Risk Level:** HIGH — **Fixed 2026-03-23** **Component:** `app/Http/Livewire/AccountInfoModal.php` **Fix:** `ProfileAuthorizationHelper::authorize($profile)` added to `loadAccounts()` after profile resolution. Manipulated session now returns HTTP 403. **Steps:** 1. Login as User A 2. Open the Account Info modal (click the balance link in the navigation) — note your own balances 3. Run session manipulation: ```bash php manipulate-session.php 5196 user ``` 4. Refresh browser 5. Open the Account Info modal again **Expected Result:** ✅ HTTP 403 Forbidden OR modal shows zero/no accounts **Security Failure:** ❌ User B's account balances are visible **Log Verification:** ```bash tail -f storage/logs/laravel.log | grep "ProfileAuthorizationHelper" ``` **Reset:** ```bash php manipulate-session.php 5195 user ``` --- ### Test 6.2: Cross-Profile-Type Balance Leakage (Organization) **Risk Level:** HIGH **Steps:** 1. Login as User A 2. Run session manipulation to switch to an organization you are NOT a member of: ```bash php manipulate-session.php org ``` 3. Refresh browser 4. Open the Account Info modal **Expected Result:** ✅ HTTP 403 Forbidden OR modal shows zero accounts **Security Failure:** ❌ Organization B's account balances are visible **Reset:** ```bash php manipulate-session.php 5195 user ``` --- ## Test Category 7: Reports — Arbitrary File Write ### Test 7.1: Malformed Base64 Chart Image Upload **Risk Level:** MEDIUM — **Fixed 2026-03-23** **Component:** `app/Http/Livewire/Reports.php` — `exportPdfWithChart()` / `exportPdfWithCharts()` **Fix:** `decodeChartImage()` helper validates PNG/JPEG magic bytes before writing. `base64_decode(..., strict: true)` used to reject malformed input. Non-image payloads abort with HTTP 422 and are logged. **Steps:** 1. Login as User A 2. Navigate to the Reports page 3. Open browser DevTools → Network tab 4. Trigger any PDF export that invokes `exportPdfWithChart` 5. Locate the Livewire POST request and copy the payload 6. Modify the `chartImage` parameter to contain a PHP webshell encoded as base64: ``` data:image/png;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+ ``` (This decodes to ``) 7. Re-send the modified request (use DevTools "Copy as fetch" then paste in Console) **Expected Result:** ✅ Request rejected (invalid MIME type), or file written but not web-executable **Security Failure:** ❌ PHP file written to an accessible path and the application executes it **Verify storage is not web-accessible:** ```bash curl -I http://localhost/storage/temp/ # Should return 404 or 403, not 200 ``` --- ### Test 7.2: Unauthenticated Livewire Chart Export Action **Risk Level:** MEDIUM — **Fixed 2026-03-23** (`abort_unless(Auth::check(), 403)` added) **Steps:** 1. Log out entirely 2. POST a Livewire request to `exportPdfWithChart` with a valid-looking base64 payload **Expected Result:** ✅ Redirected to login, or 401/403 response **Security Failure:** ❌ File written to temp storage without authentication --- ## Test Category 8: ExportProfileData — Authorization Verification ### Test 8.1: Unauthorized Transaction Export via Session Manipulation **Risk Level:** HIGH **Component:** `app/Http/Livewire/Profile/ExportProfileData.php` — `exportTransactions()` **Note:** This component DOES call `ProfileAuthorizationHelper::authorize()`. This test verifies the protection works correctly. **Steps:** 1. Login as User A 2. Navigate to Profile → Export Data 3. Run session manipulation: ```bash php manipulate-session.php 5196 user ``` 4. Refresh browser 5. Attempt to export transactions (any format) **Expected Result:** ✅ HTTP 403 Forbidden **Security Failure:** ❌ User B's transactions are exported **Log Verification:** ```bash tail -f storage/logs/laravel.log | grep "ProfileAuthorizationHelper" ``` Should show: "Unauthorized User profile access attempt" **Reset:** ```bash php manipulate-session.php 5195 user ``` --- ### Test 8.2: Unauthorized Messages Export **Risk Level:** HIGH **Steps:** 1. Login as User A 2. Run session manipulation: ```bash php manipulate-session.php 5196 user ``` 3. Refresh browser 4. Attempt to export messages **Expected Result:** ✅ HTTP 403 Forbidden **Security Failure:** ❌ User B's private messages exported **Reset:** ```bash php manipulate-session.php 5195 user ``` --- ### Test 8.3: Unauthorized Contacts Export **Risk Level:** MEDIUM **Steps:** 1. Login as User A 2. Run session manipulation: ```bash php manipulate-session.php 5196 user ``` 3. Refresh browser 4. Attempt to export contacts **Expected Result:** ✅ HTTP 403 Forbidden **Security Failure:** ❌ User B's contact list exported **Reset:** ```bash php manipulate-session.php 5195 user ``` --- ## Quick Reference | Action | Command | |--------|---------| | Change to User B | `php manipulate-session.php 5196 user` | | Change to Org B (ID 1) | `php manipulate-session.php 1 org` | | Change to Bank A (ID 1) | `php manipulate-session.php 1 bank` | | Reset to User A | `php manipulate-session.php 5195 user` | | Monitor logs | `tail -f storage/logs/laravel.log \| grep ProfileAuthorizationHelper` | | Check temp dir not web-accessible | `curl -I http://localhost/storage/temp/` |