Initial commit
This commit is contained in:
519
SECURITY_TESTING_GUIDE.md
Normal file
519
SECURITY_TESTING_GUIDE.md
Normal file
@@ -0,0 +1,519 @@
|
||||
# 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/` |
|
||||
Reference in New Issue
Block a user