![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/soundstudiopro.com/private_html/ |
# Current Security Implementation - Audio Protection System
## 🔒 What's Implemented
### 1. **User/Session-Bound Tokens** ✅
**Location:** `utils/audio_token.php`
**How it works:**
- Tokens are generated using HMAC-SHA256 signature
- Token includes: `trackId|variationIndex|expires|user_id|session_id`
- Token is bound to the specific user AND session who generated it
**Code:**
```php
// Token generation includes user context
$userContext = ($userId ?? '') . '|' . $currentSessionId;
$data = $trackId . '|' . ($variationIndex ?? '') . '|' . $expires . '|' . $userContext;
$signature = hash_hmac('sha256', $data, AUDIO_TOKEN_SECRET);
$token = substr($signature, 0, 16); // First 16 chars
```
**What this prevents:**
- ❌ **URL Sharing**: If User A copies a URL and gives it to User B, it won't work
- ❌ **Cross-Session Access**: Token from one browser session won't work in another
- ❌ **Token Replay**: Tokens expire after 5 minutes
---
### 2. **Access Control Check (BEFORE Token Validation)** ✅
**Location:** `utils/play_audio.php` (lines 53-78)
**How it works:**
1. **First** checks if user has access to the track
2. **Then** validates the token
3. This prevents token bypass attacks
**Access Rules:**
- **Private Track**: Only owner can access (`user_id` matches track owner)
- **Public Track**: Anyone with valid token can access (`is_public = 1`)
- **NULL/0 Track**: Treated as private (only owner)
**Code:**
```php
// Check access FIRST
$isOwner = ($user_id && $track['user_id'] == $user_id);
$isPublic = ($track['is_public'] == 1);
if (!$isOwner && !$isPublic) {
// Deny immediately - don't even check token
http_response_code(403);
exit;
}
```
**What this prevents:**
- ❌ **Token Bypass**: Even with valid token, private tracks are blocked
- ❌ **Unauthorized Access**: Non-owners can't access private tracks
---
### 3. **Token Validation with User/Session Binding** ✅
**Location:** `utils/play_audio.php` (lines 80-101)
**How it works:**
- Validates token signature matches current user + session
- For public tracks, tries guest mode fallback (handles login/logout edge cases)
- Uses constant-time comparison (`hash_equals`) to prevent timing attacks
**Code:**
```php
$tokenValid = validateAudioToken($trackId, $variationIndex, $token, $expires, $user_id, $session_id);
if (!$tokenValid && $isPublic) {
// Try guest mode (in case user logged in/out)
$tokenValid = validateAudioToken($trackId, $variationIndex, $token, $expires, null, $session_id);
}
```
**What this prevents:**
- ❌ **Token Forgery**: Can't create valid tokens without secret key
- ❌ **Token Reuse**: Tokens only work for the user/session who generated them
- ❌ **Timing Attacks**: Constant-time comparison prevents side-channel attacks
---
### 4. **Token Expiration (5 minutes)** ✅
**Location:** `utils/audio_token.php` (line 12)
**How it works:**
- Tokens expire 5 minutes after generation
- Expiration timestamp is included in token signature
- Expired tokens are rejected immediately
**What this prevents:**
- ❌ **Long-term URL Sharing**: URLs become invalid after 5 minutes
- ❌ **Stale Token Reuse**: Old tokens can't be used
---
### 5. **Path Hiding** ✅
**Location:** `utils/play_audio.php`
**How it works:**
- Direct MP3 file paths are never exposed
- All audio access goes through `/utils/play_audio.php?id=...&token=...`
- Actual file paths (`/audio_files/...`) are hidden from users
**What this prevents:**
- ❌ **Direct File Access**: Can't access files without going through proxy
- ❌ **Path Discovery**: Actual file structure is hidden
---
## 🔄 Request Flow
```
1. User visits track.php
↓
2. Frontend calls getSignedAudioUrl(trackId, userId, sessionId)
↓
3. Token generated: HMAC(trackId|variation|expires|user_id|session_id)
↓
4. URL created: /utils/play_audio.php?id=323&token=abc123&expires=1234567890
↓
5. User's browser requests audio
↓
6. play_audio.php checks:
a. Track exists? ✅
b. User has access? (owner OR public) ✅
c. Token valid? (matches user+session) ✅
d. Token not expired? ✅
↓
7. If all checks pass → Serve audio
If any check fails → 403 Access Denied
```
---
## 🛡️ Security Layers
### Layer 1: Access Control
- **What:** Checks if user owns track OR track is public
- **When:** BEFORE token validation
- **Prevents:** Token bypass attacks
### Layer 2: Token Validation
- **What:** Validates token signature matches user+session
- **When:** AFTER access control
- **Prevents:** Token sharing, forgery, replay
### Layer 3: Expiration
- **What:** Tokens expire after 5 minutes
- **When:** During token validation
- **Prevents:** Long-term URL sharing
### Layer 4: Path Hiding
- **What:** Direct file paths never exposed
- **When:** Always
- **Prevents:** Direct file access
---
## ✅ What Works
1. **Tokens are NOT shareable** - Bound to user+session
2. **Private tracks protected** - Access control before token check
3. **URLs expire** - 5 minute expiration
4. **Paths hidden** - All access through proxy
5. **Timing attack protection** - Constant-time comparison
---
## ⚠️ What It DOESN'T Prevent
1. **Direct Download** - If someone has a valid token, they can download the MP3
- The file is served as-is, not encrypted
- Browser can save it during playback
2. **Screen Recording** - Users can record audio from their speakers
3. **Token Extraction** - If someone has access to generate tokens, they can extract them
---
## 📊 Security Level
**Current Protection:** **Medium-High**
- ✅ Prevents URL sharing
- ✅ Prevents unauthorized access
- ✅ Prevents token forgery
- ❌ Doesn't prevent downloads (if token is valid)
- ❌ Doesn't encrypt audio files
**For Higher Security:**
- Would need HLS encryption (segments encrypted, keys server-side)
- Would need DRM (Digital Rights Management)
- Would need watermarking
---
## 🔍 Testing the Protection
### Test 1: URL Sharing
1. Copy URL from track.php: `/utils/play_audio.php?id=323&token=abc123&expires=1234567890`
2. Open in private/incognito window
3. **Expected:** "Access denied - invalid or expired token" ✅
### Test 2: Private Track Access
1. Log in as User A
2. Try to access User B's private track
3. **Expected:** "Access denied" (even with valid token) ✅
### Test 3: Expired Token
1. Wait 5+ minutes after generating token
2. Try to use the URL
3. **Expected:** "Access denied - invalid or expired token" ✅
---
## 📝 Summary
**What's Protected:**
- ✅ URL sharing between users
- ✅ Unauthorized access to private tracks
- ✅ Token forgery/replay
- ✅ Direct file path exposure
**What's NOT Protected:**
- ❌ Downloads (if user has valid token)
- ❌ Screen/audio recording
- ❌ File encryption
**Security Level:** Medium-High (good for most use cases, but not DRM-level)