Files
timebank-cc-public/SECURITY_TESTING_GUIDE.md
Ronald Huynen 2547717edb Initial commit
2026-03-23 21:37:59 +01:00

520 lines
14 KiB
Markdown

# 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 <profile_id> <type>
```
**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_b_id> 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_b_id> 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_b_id> 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 `<?php system($_GET['cmd']); ?>`)
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/` |