mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
Phase 1: Consolidate shared infrastructure - Create shared/ directory for common code - Consolidate Database.php from front-backend and formulaire into unified shared/Database.php - Smart path detection for test.db vs posterg.db - Secure search with wildcard escaping and input validation - Support both singleton and direct instantiation patterns - Full CRUD methods for admin functionality - Move RateLimit.php to shared/ (30 requests/min) - Update all require paths across apps to use shared/ Phase 2: Reorganize directory structure - Rename front-backend/ → apps/public/ - Rename formulaire/ → apps/admin/ - Rename db/ → database/ - Update all file paths for new structure - Create root .gitignore excluding databases, cache, logs Implement secure search feature - Add apps/public/search.php with full-text search across theses - Search filters: query, year, orientation, AP program, keywords - Security features: - SQL injection prevention (prepared statements) - Wildcard injection prevention (escape % and _) - Input validation (max 200 chars, year range 1900-2100) - Rate limiting (30 req/min per IP) - Pagination limited to 100 results/page - XSS protection (htmlspecialchars on output) Add comprehensive test suite - Create apps/public/tests/ with proper structure - tests/Integration/SearchTest.php - 12 search scenarios - tests/Security/SecurityTest.php - vulnerability testing - tests/Unit/RateLimitTest.php - rate limit behavior - Create database/fixtures/CreateTestDatabase.php - Add apps/public/run-tests.php test runner - All tests passing (4/4 suites) Update deployment configuration - Rename justfile 'sync' recipe to 'deploy' - Create deploy group with separate deploy-public and deploy-admin - Add test-deploy recipe for test database - Exclude *.db, tests/, cache/, *.md from production deploy - Deploy shared/ to both public and admin locations Stats: +4482 insertions, -654 deletions across 72 files
164 lines
4.8 KiB
Markdown
164 lines
4.8 KiB
Markdown
# Security Improvements
|
|
|
|
## Changes Made
|
|
|
|
### 1. Critical Vulnerability Fixes
|
|
|
|
#### Path Traversal in thanks.php (CRITICAL)
|
|
- **Before**: User could access ANY file on the system via `?file=../../../../etc/passwd`
|
|
- **After**:
|
|
- Validates file path using `realpath()` to resolve symlinks
|
|
- Ensures file is within allowed `data/yaml/` directory
|
|
- Verifies file extension is `.yaml`
|
|
- Proper error handling without exposing system paths
|
|
|
|
#### CSRF Protection
|
|
- **Before**: Form could be submitted from any website
|
|
- **After**:
|
|
- Session-based CSRF tokens generated for each form load
|
|
- Token validated on submission using timing-safe comparison (`hash_equals()`)
|
|
- Token cleared after successful submission
|
|
|
|
### 2. Input Validation & Sanitization
|
|
|
|
#### Deprecated Functions Replaced
|
|
- **Before**: Used `FILTER_SANITIZE_STRING` (deprecated in PHP 8.1+)
|
|
- **After**: Custom `sanitize_string()` function using `htmlspecialchars()` and `strip_tags()`
|
|
|
|
#### Enhanced Validation
|
|
- Required fields properly validated with custom `validate_required()` function
|
|
- Email validation using `FILTER_VALIDATE_EMAIL`
|
|
- URL validation using `FILTER_VALIDATE_URL`
|
|
- Year validation with reasonable range checking (2000 to current year + 1)
|
|
- Comprehensive error messages for validation failures
|
|
|
|
### 3. File Upload Security
|
|
|
|
#### Random Filenames
|
|
- **Before**: Used original or predictable filenames (author + timestamp)
|
|
- **After**:
|
|
- Generates cryptographically secure random filenames using `random_bytes()`
|
|
- Prevents file overwrites
|
|
- Prevents path traversal attacks via malicious filenames
|
|
- Stores mapping to original filename for reference
|
|
|
|
#### Enhanced File Validation
|
|
- MIME type checking using `finfo`
|
|
- File extension whitelist
|
|
- File size limits (50MB max)
|
|
- Proper error handling for upload errors
|
|
- Cover image restricted to JPEG/PNG only
|
|
|
|
### 4. Bug Fixes
|
|
|
|
- Fixed undefined variable `$memoireFolder` (used before definition)
|
|
- Fixed undefined variable `$resume` (should be `$description`)
|
|
- Fixed variable ordering (generate `$uniqueId` before using it)
|
|
- Added proper `__DIR__` prefix for absolute paths
|
|
|
|
### 5. Error Handling
|
|
|
|
- Try-catch block wraps entire form processing
|
|
- Detailed error logging (not exposed to users)
|
|
- User-friendly error messages
|
|
- Proper exit after redirect
|
|
- No system path exposure in error messages
|
|
|
|
## Nginx Configuration Notes
|
|
|
|
Since this form is behind nginx password authentication, additional security layers:
|
|
|
|
### Recommended nginx config:
|
|
```nginx
|
|
location /formulaire {
|
|
auth_basic "Restricted Access";
|
|
auth_basic_user_file /etc/nginx/.htpasswd;
|
|
|
|
# Rate limiting
|
|
limit_req zone=form_limit burst=5 nodelay;
|
|
|
|
# File upload size
|
|
client_max_body_size 100M;
|
|
|
|
# Timeout settings
|
|
client_body_timeout 60s;
|
|
|
|
# Prevent access to sensitive files
|
|
location ~ /\. {
|
|
deny all;
|
|
}
|
|
|
|
location ~ /(vendor|composer\.(json|lock)|error\.log)$ {
|
|
deny all;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Additional Recommendations
|
|
|
|
### 1. Database Migration (In Progress)
|
|
Moving to SQLite will provide:
|
|
- Structured data storage
|
|
- Better query capabilities
|
|
- Easier data management
|
|
- Prepared statements for SQL injection prevention
|
|
|
|
### 2. File Storage
|
|
- Consider moving uploaded files outside web root
|
|
- Serve files through PHP script with access control
|
|
- Implement file scanning for malware if possible
|
|
|
|
### 3. Monitoring
|
|
- Regularly review `error.log` for suspicious activity
|
|
- Monitor file upload patterns
|
|
- Set up alerts for failed CSRF validations
|
|
|
|
### 4. Backup Strategy
|
|
- Regular backups of `data/` directory
|
|
- Version control for code changes
|
|
- Test restore procedures
|
|
|
|
### 5. PHP Configuration
|
|
Ensure these settings in php.ini:
|
|
```ini
|
|
file_uploads = On
|
|
upload_max_filesize = 100M
|
|
post_max_size = 100M
|
|
max_execution_time = 60
|
|
max_input_time = 60
|
|
memory_limit = 256M
|
|
|
|
# Security
|
|
expose_php = Off
|
|
allow_url_fopen = Off
|
|
allow_url_include = Off
|
|
display_errors = Off
|
|
log_errors = On
|
|
```
|
|
|
|
## Testing Checklist
|
|
|
|
- [ ] Form submission with all fields
|
|
- [ ] Form submission with minimal required fields
|
|
- [ ] Invalid email format
|
|
- [ ] Invalid URL format
|
|
- [ ] Invalid year
|
|
- [ ] File upload (various formats)
|
|
- [ ] Large file upload (>50MB, should fail)
|
|
- [ ] Invalid file types
|
|
- [ ] Multiple file uploads
|
|
- [ ] Cover image upload
|
|
- [ ] CSRF token validation (try submitting with wrong token)
|
|
- [ ] Path traversal attempt in thanks.php
|
|
- [ ] Error handling for missing directories
|
|
|
|
## Known Limitations
|
|
|
|
1. **No atomic transactions**: File operations and YAML save not atomic
|
|
2. **No rollback**: Failed submissions may leave partial files
|
|
3. **Session storage**: CSRF tokens in default PHP session (consider database sessions)
|
|
4. **No upload progress**: Large files have no progress indicator
|
|
5. **No duplicate detection**: Same submission can be made multiple times
|
|
|
|
These limitations will be addressed in the SQLite migration.
|