diff --git a/SECURITY_INSTALLATION.md b/SECURITY_INSTALLATION.md deleted file mode 100644 index 60cd302c3..000000000 --- a/SECURITY_INSTALLATION.md +++ /dev/null @@ -1,193 +0,0 @@ -# CyberPanel Secure Installation Guide - -## Overview - -This document describes the secure installation process for CyberPanel that eliminates hardcoded passwords and implements environment-based configuration. - -## Security Improvements - -### ✅ **Fixed Security Vulnerabilities** - -1. **Hardcoded Database Passwords** - Now generated securely during installation -2. **Hardcoded Django Secret Key** - Now generated using cryptographically secure random generation -3. **Environment Variables** - All sensitive configuration moved to `.env` file -4. **File Permissions** - `.env` file set to 600 (owner read/write only) - -### 🔐 **Security Features** - -- **Cryptographically Secure Passwords**: Uses Python's `secrets` module for password generation -- **Environment-based Configuration**: Sensitive data stored in `.env` file, not in code -- **Secure File Permissions**: Environment files protected with 600 permissions -- **Credential Backup**: Automatic backup of credentials for recovery -- **Fallback Security**: Maintains backward compatibility with fallback method - -## Installation Process - -### 1. **Automatic Secure Installation** - -The installation script now automatically: - -1. Generates secure random passwords for: - - MySQL root user - - CyberPanel database user - - Django secret key - -2. Creates `.env` file with secure configuration: - ```bash - # Generated during installation - SECRET_KEY=your_64_character_secure_key - DB_PASSWORD=your_24_character_secure_password - ROOT_DB_PASSWORD=your_24_character_secure_password - ``` - -3. Creates `.env.backup` file for credential recovery -4. Sets secure file permissions (600) on all environment files - -### 2. **Manual Installation** (if needed) - -If you need to manually generate environment configuration: - -```bash -cd /usr/local/CyberCP -python install/env_generator.py /usr/local/CyberCP -``` - -## File Structure - -``` -/usr/local/CyberCP/ -├── .env # Main environment configuration (600 permissions) -├── .env.backup # Credential backup (600 permissions) -├── .env.template # Template for manual configuration -├── .gitignore # Prevents .env files from being committed -└── CyberCP/ - └── settings.py # Updated to use environment variables -``` - -## Security Best Practices - -### ✅ **Do's** - -- Keep `.env` and `.env.backup` files secure -- Record credentials from `.env.backup` and delete the file after installation -- Use strong, unique passwords for production deployments -- Regularly rotate database passwords -- Monitor access to environment files - -### ❌ **Don'ts** - -- Never commit `.env` files to version control -- Don't share `.env` files via insecure channels -- Don't use default passwords in production -- Don't leave `.env.backup` files on the system after recording credentials - -## Recovery - -### **Lost Credentials** - -If you lose your database credentials: - -1. Check if `.env.backup` file exists: - ```bash - sudo cat /usr/local/CyberCP/.env.backup - ``` - -2. If backup doesn't exist, you'll need to reset MySQL passwords using MySQL recovery procedures - -### **Regenerate Environment** - -To regenerate environment configuration: - -```bash -cd /usr/local/CyberCP -sudo python install/env_generator.py /usr/local/CyberCP -``` - -## Configuration Options - -### **Environment Variables** - -| Variable | Description | Default | -|----------|-------------|---------| -| `SECRET_KEY` | Django secret key | Generated (64 chars) | -| `DB_PASSWORD` | CyberPanel DB password | Generated (24 chars) | -| `ROOT_DB_PASSWORD` | MySQL root password | Generated (24 chars) | -| `DEBUG` | Debug mode | False | -| `ALLOWED_HOSTS` | Allowed hosts | localhost,127.0.0.1,hostname | - -### **Custom Configuration** - -To use custom passwords during installation: - -```bash -python install/env_generator.py /usr/local/CyberCP "your_root_password" "your_db_password" -``` - -## Troubleshooting - -### **Installation Fails** - -If the new secure installation fails: - -1. Check installation logs for error messages -2. The system will automatically fallback to the original installation method -3. Verify Python dependencies are installed: - ```bash - pip install python-dotenv - ``` - -### **Environment Loading Issues** - -If Django can't load environment variables: - -1. Ensure `.env` file exists and has correct permissions: - ```bash - ls -la /usr/local/CyberCP/.env - # Should show: -rw------- 1 root root - ``` - -2. Install python-dotenv if missing: - ```bash - pip install python-dotenv - ``` - -## Migration from Old Installation - -### **Existing Installations** - -For existing CyberPanel installations with hardcoded passwords: - -1. **Backup current configuration**: - ```bash - cp /usr/local/CyberCP/CyberCP/settings.py /usr/local/CyberCP/CyberCP/settings.py.backup - ``` - -2. **Generate new environment configuration**: - ```bash - cd /usr/local/CyberCP - python install/env_generator.py /usr/local/CyberCP - ``` - -3. **Update settings.py** (already done in new installations): - - The settings.py file now supports environment variables - - It will fallback to hardcoded values if .env is not available - -4. **Test the configuration**: - ```bash - cd /usr/local/CyberCP - python manage.py check - ``` - -## Support - -For issues with the secure installation: - -1. Check the installation logs -2. Verify file permissions -3. Ensure all dependencies are installed -4. Review the fallback installation method if needed - ---- - -**Security Notice**: This installation method significantly improves security by eliminating hardcoded credentials. Always ensure proper file permissions and secure handling of environment files. - diff --git a/baseTemplate/views.py b/baseTemplate/views.py index e9da11248..eedf0d871 100644 --- a/baseTemplate/views.py +++ b/baseTemplate/views.py @@ -1129,8 +1129,9 @@ def blockIPAddress(request): 'error': 'IP address is required' }), content_type='application/json', status=400) - # Validate IP address format + # Validate IP address format and check for private/reserved ranges import re + import ipaddress ip_pattern = r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' if not re.match(ip_pattern, ip_address): return HttpResponse(json.dumps({ @@ -1138,39 +1139,78 @@ def blockIPAddress(request): 'error': 'Invalid IP address format' }), content_type='application/json', status=400) + # Check for private/reserved IP ranges to prevent self-blocking + try: + ip_obj = ipaddress.ip_address(ip_address) + if ip_obj.is_private or ip_obj.is_loopback or ip_obj.is_link_local or ip_obj.is_reserved: + return HttpResponse(json.dumps({ + 'status': 0, + 'error': 'Cannot block private, loopback, link-local, or reserved IP addresses' + }), content_type='application/json', status=400) + + # Additional check for common problematic ranges + if (ip_address.startswith('127.') or # Loopback + ip_address.startswith('169.254.') or # Link-local + ip_address.startswith('224.') or # Multicast + ip_address.startswith('255.') or # Broadcast + ip_address in ['0.0.0.0', '::1']): # Invalid/loopback + return HttpResponse(json.dumps({ + 'status': 0, + 'error': 'Cannot block system or reserved IP addresses' + }), content_type='application/json', status=400) + + except ValueError: + return HttpResponse(json.dumps({ + 'status': 0, + 'error': 'Invalid IP address' + }), content_type='application/json', status=400) + # Use firewalld (CSF has been discontinued) firewall_cmd = 'firewalld' try: - # Verify firewalld is active - firewalld_check = ProcessUtilities.outputExecutioner('systemctl is-active firewalld') - if not (firewalld_check and 'active' in firewalld_check): + # Verify firewalld is active using subprocess for better security + import subprocess + firewalld_check = subprocess.run(['systemctl', 'is-active', 'firewalld'], + capture_output=True, text=True, timeout=10) + if not (firewalld_check.returncode == 0 and 'active' in firewalld_check.stdout): return HttpResponse(json.dumps({ 'status': 0, 'error': 'Firewalld is not active. Please enable firewalld service.' }), content_type='application/json', status=500) + except subprocess.TimeoutExpired: + return HttpResponse(json.dumps({ + 'status': 0, + 'error': 'Timeout checking firewalld status' + }), content_type='application/json', status=500) except Exception as e: return HttpResponse(json.dumps({ 'status': 0, 'error': f'Cannot check firewalld status: {str(e)}' }), content_type='application/json', status=500) - # Block the IP address using firewalld + # Block the IP address using firewalld with subprocess for better security success = False error_message = '' try: - # Use firewalld to block IP - command = f'firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address={ip_address} drop"' - result = ProcessUtilities.executioner(command) - if result == 0: + # Use subprocess with explicit argument lists to prevent injection + rich_rule = f'rule family=ipv4 source address={ip_address} drop' + add_rule_cmd = ['firewall-cmd', '--permanent', '--add-rich-rule', rich_rule] + + # Execute the add rule command + result = subprocess.run(add_rule_cmd, capture_output=True, text=True, timeout=30) + if result.returncode == 0: # Reload firewall rules - reload_result = ProcessUtilities.executioner('firewall-cmd --reload') - if reload_result == 0: + reload_cmd = ['firewall-cmd', '--reload'] + reload_result = subprocess.run(reload_cmd, capture_output=True, text=True, timeout=30) + if reload_result.returncode == 0: success = True else: - error_message = 'Failed to reload firewall rules' + error_message = f'Failed to reload firewall rules: {reload_result.stderr}' else: - error_message = 'Failed to add firewall rule' + error_message = f'Failed to add firewall rule: {result.stderr}' + except subprocess.TimeoutExpired: + error_message = 'Firewall command timed out' except Exception as e: error_message = f'Firewall command failed: {str(e)}' diff --git a/guides/FIREWALL_BLOCKING_FEATURE.md b/guides/FIREWALL_BLOCKING_FEATURE.md index 5a12143af..65c4a18fd 100644 --- a/guides/FIREWALL_BLOCKING_FEATURE.md +++ b/guides/FIREWALL_BLOCKING_FEATURE.md @@ -80,23 +80,56 @@ firewall-cmd --reload 1. **Admin-Only Access**: Feature restricted to administrators 2. **Premium Feature**: Requires CyberPanel addons -3. **IP Validation**: Validates IP address format before blocking -4. **Firewalld Verification**: Ensures firewalld service is active -5. **Audit Logging**: All blocking actions are logged -6. **Error Handling**: Comprehensive error handling and user feedback +3. **Enhanced IP Validation**: Validates IP address format and prevents blocking private/reserved ranges +4. **Command Injection Protection**: Uses subprocess with explicit argument lists +5. **Timeout Protection**: Prevents hanging processes with configurable timeouts +6. **Firewalld Verification**: Ensures firewalld service is active +7. **Audit Logging**: All blocking actions are logged +8. **Comprehensive Error Handling**: Detailed error messages with captured stderr ## Error Handling The feature includes robust error handling for: -- Invalid IP addresses +- Invalid IP addresses and formats +- Private/reserved IP address ranges - Firewalld service not active -- Firewall command failures +- Firewall command failures and timeouts - Network connectivity issues - Permission errors +- Command injection attempts +- Process timeouts ## Testing -A test script is provided (`test_firewall_blocking.py`) for manual testing, though the feature is best tested through the web interface. +A test script is provided for basic functionality testing: +- `test_firewall_blocking.py` - Basic functionality testing + +The feature is best tested through the web interface with various IP address types. + +## Enhanced Security Features + +### IP Range Validation +The system now prevents blocking of: +- **Private IP ranges**: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 +- **Loopback addresses**: 127.0.0.0/8 +- **Link-local addresses**: 169.254.0.0/16 +- **Multicast addresses**: 224.0.0.0/4 +- **Broadcast addresses**: 255.255.255.255 +- **Reserved addresses**: 0.0.0.0 + +### Command Execution Security +- **Subprocess with explicit arguments**: Prevents command injection +- **Timeout protection**: 10s for status checks, 30s for firewall commands +- **Error capture**: Captures both stdout and stderr for better debugging +- **No shell interpretation**: Eliminates shell injection vulnerabilities + +### Example Error Messages +``` +"Cannot block private, loopback, link-local, or reserved IP addresses" +"Cannot block system or reserved IP addresses" +"Timeout checking firewalld status" +"Firewall command timed out" +``` ## Browser Compatibility diff --git a/test.php b/test.php deleted file mode 100644 index 57a4844d4..000000000 --- a/test.php +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/test.sh b/test.sh deleted file mode 100755 index e69de29bb..000000000