Documentation Index Fetch the complete documentation index at: https://mintlify.com/IvBanzaga/Refugio/llms.txt
Use this file to discover all available pages before exploring further.
Security Best Practices
This guide covers security features, best practices, and production deployment considerations for the Refugio mountain refuge reservation system.
Built-in Security Features
The Refugio system implements several security measures to protect user data and prevent attacks.
Password Security
Bcrypt Password Hashing The system uses PHP’s password_hash() function with PASSWORD_BCRYPT to securely store passwords. What this means :
Passwords are never stored in plain text
Each password has a unique salt
Even administrators cannot see user passwords
Passwords are verified using password_verify() during login
Implementation (from functions.php:75):
$password_hash = password_hash ( $datos [ 'password' ], PASSWORD_BCRYPT );
Verification (from login.php:19):
if ( $user && password_verify ( $password , $user [ 'password' ])) {
// Login successful
}
Session Security
Session Fixation Prevention The system regenerates session IDs on login to prevent session fixation attacks.
Implementation (from login.php:20 and viewAdmin.php:14):
session_regenerate_id ( true ); // Prevents session fixation attacks
How it works :
User logs in with credentials
Old session ID is destroyed
New session ID is generated
User is associated with the new session
This prevents attackers from hijacking sessions by fixing session IDs.
XSS Protection All user inputs are sanitized using the sanitize_input() function to prevent Cross-Site Scripting (XSS) attacks.
Implementation (from functions.php:1452):
function sanitize_input ( $data )
{
$data = trim ( $data ); // Remove whitespace
$data = stripslashes ( $data ); // Remove backslashes
$data = htmlspecialchars ( $data , ENT_QUOTES , 'UTF-8' ); // Escape HTML entities
return $data ;
}
Usage (from viewAdmin.php:28-37):
$datos = [
'num_socio' => sanitize_input ( $_POST [ 'num_socio' ]),
'dni' => sanitize_input ( $_POST [ 'dni' ]),
'email' => sanitize_input ( $_POST [ 'email' ]),
// ... all user inputs are sanitized
];
SQL Injection Prevention
Prepared Statements All database queries use PDO prepared statements with parameter binding to prevent SQL injection.
Example (from functions.php:16):
$stmt = $conexion -> prepare ( " SELECT id, email, password , rol, nombre, apellido1 FROM usuarios WHERE email = :email" );
$stmt -> bindParam ( ':email' , $email );
$stmt -> execute ();
Why this is secure :
User input is never directly concatenated into SQL queries
Parameters are properly escaped by PDO
SQL injection attacks are effectively prevented
Role-Based Access Control
Authentication & Authorization The system enforces role-based access control with strict session validation.
Admin panel protection (from viewAdmin.php:10-13):
if ( ! isset ( $_SESSION [ 'userId' ]) || $_SESSION [ 'rol' ] !== 'admin' ) {
header ( 'Location: login.php' );
exit ;
}
User panel protection (from viewSocio.php:11-14):
if ( ! isset ( $_SESSION [ 'userId' ]) || ( $_SESSION [ 'rol' ] ?? '' ) !== 'user' ) {
header ( 'Location: login.php' );
exit ;
}
Protected admin user (from viewAdmin.php:52-58):
// Prevent modification of main admin account
$usuario_actual = obtener_usuario ( $conexionPDO , $id );
if ( $usuario_actual && $usuario_actual [ 'email' ] === 'admin@hostel.com' ) {
$mensaje = "No se puede modificar el usuario administrador principal" ;
$tipo_mensaje = 'danger' ;
break ;
}
Password Management
Creating Strong Passwords
Minimum requirements
While the system doesn’t enforce complexity, follow these guidelines:
Minimum 8 characters (preferably 12+)
Mix of uppercase and lowercase letters
Include numbers and special characters
Avoid common words or personal information
Use a password manager
Consider using a password manager to:
Generate strong, unique passwords
Store passwords securely
Automatically fill login forms
Good password examples :
Tr4il$Runner2024!
M0unt@inH!ke#89
Refug10*Climb3r
Bad password examples (never use these):
password123
admin
123456
Your name or club name
Changing Your Password
For Members
For Administrators
Navigate to profile
Click Mi Perfil in the sidebar
Enter current password
Provide your current password for verification
Enter new password
Type your new strong password twice
Save changes
Click “Cambiar Contraseña”
Administrators can reset user passwords:
Edit user
In the Users section, click edit for the user
Enter new password
Fill in the password field with a new password
Save
Click “Actualizar Usuario”
Inform the user
Securely communicate the new password to the user
Never send passwords via email. Use a secure communication channel.
Password Reset Workflow
If a user forgets their password:
User contacts administrator
User requests a password reset via secure communication
Administrator verifies identity
Admin confirms the user’s identity using member number and other details
Administrator resets password
Admin sets a temporary password via user edit form
Secure communication
Admin communicates the temporary password securely (in person, phone, or encrypted message)
User changes password
User logs in with temporary password and immediately changes it
Consider implementing a self-service password reset system with email verification for improved security and user experience.
HTTPS and Transport Security
Why HTTPS is Critical
Never run the Refugio system over HTTP in production. All data, including passwords, is transmitted in plain text over HTTP.
Without HTTPS :
Passwords sent in plain text during login
Session cookies can be intercepted
All user data is visible to network attackers
Man-in-the-middle attacks are possible
With HTTPS :
All communication is encrypted
Passwords and data are protected in transit
Session cookies are secure
Users can trust the connection
Implementing HTTPS
Obtain an SSL/TLS certificate
Options:
Let’s Encrypt : Free, automated certificates (recommended)
Commercial CA : Purchase from Digicert, Sectigo, etc.
Self-signed : Only for testing, never for production
Configure your web server
For Apache (httpd.conf or virtual host):< VirtualHost *:443 >
ServerName refugio.yourclub.com
SSLEngine on
SSLCertificateFile /path/to/certificate.crt
SSLCertificateKeyFile /path/to/private.key
SSLCertificateChainFile /path/to/chain.crt
# Strong SSL configuration
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1. 1
SSLCipherSuite HIGH:!aNULL:!MD5
DocumentRoot /var/www/refugio
# ... rest of configuration
</ VirtualHost >
For Nginx (nginx.conf):server {
listen 443 ssl http2;
server_name refugio.yourclub.com;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;
# Strong SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on ;
root /var/www/refugio;
# ... rest of configuration
}
Redirect HTTP to HTTPS
Force all traffic to use HTTPS: Apache (.htaccess):RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R= 301 ]
Nginx :server {
listen 80 ;
server_name refugio.yourclub.com;
return 301 https://$ server_name $ request_uri ;
}
Test your configuration
Use SSL Labs SSL Test to verify:
Certificate is valid and trusted
Strong cipher suites are used
No security warnings
Grade A or A+ rating
Secure Session Cookies
Modify session settings for HTTPS (in conexion.php or main config file):
// Set secure session cookie parameters
ini_set ( 'session.cookie_httponly' , 1 ); // Prevent JavaScript access
ini_set ( 'session.cookie_secure' , 1 ); // Only send over HTTPS
ini_set ( 'session.cookie_samesite' , 'Strict' ); // CSRF protection
session_start ();
CSRF Protection
Current State
The current Refugio system does not implement CSRF tokens . This should be added for production deployments.
Implementing CSRF Protection
Generate CSRF token on login
Add to login.php after successful authentication: // Generate CSRF token
$_SESSION [ 'csrf_token' ] = bin2hex ( random_bytes ( 32 ));
Include token in all forms
Add a hidden field to every POST form: < form method = "post" action = "viewAdmin.php" >
< input type = "hidden" name = "csrf_token" value = "<?php echo $_SESSION ['csrf_token']; ?>" >
<!-- rest of form fields -->
</ form >
Validate token on submission
At the start of form processing: if ( $_SERVER [ 'REQUEST_METHOD' ] === 'POST' ) {
// Verify CSRF token
if ( ! isset ( $_POST [ 'csrf_token' ]) ||
$_POST [ 'csrf_token' ] !== $_SESSION [ 'csrf_token' ]) {
die ( 'CSRF token validation failed' );
}
// Process form...
}
Regenerate token after use (optional)
For extra security, regenerate after each request: // After validating token
$_SESSION [ 'csrf_token' ] = bin2hex ( random_bytes ( 32 ));
Production Deployment Checklist
Before deploying to production, ensure all security measures are in place:
Pre-Deployment Security
Critical Security Items
Disable error display
// In production configuration
ini_set ( 'display_errors' , 0 );
ini_set ( 'display_startup_errors' , 0 );
error_reporting ( 0 );
// Log errors instead
ini_set ( 'log_errors' , 1 );
ini_set ( 'error_log' , '/var/log/php-errors.log' );
Remove development code
Remove or comment out (from viewAdmin.php:2-4 and viewSocio.php:6-8): // DELETE THESE LINES IN PRODUCTION:
ini_set ( 'display_errors' , 1 );
ini_set ( 'display_startup_errors' , 1 );
error_reporting ( E_ALL );
Secure database credentials
Store database credentials in a file outside the web root
Use environment variables for sensitive configuration
Restrict file permissions: chmod 600 config.php
Change default admin password
Change password for admin@hostel.com
Use a strong, unique password
Store it in a password manager
Enable HTTPS
Install valid SSL certificate
Configure secure session cookies
Redirect all HTTP to HTTPS
Implement CSRF protection
Add CSRF tokens to all forms
Validate tokens on submission
Server Configuration
Web Server Security
Restrict file permissions
# Set ownership
chown -R www-data:www-data /var/www/refugio
# Set directory permissions
find /var/www/refugio -type d -exec chmod 755 {} \;
# Set file permissions
find /var/www/refugio -type f -exec chmod 644 {} \;
# Protect sensitive files
chmod 600 /var/www/refugio/conexion.php
Disable directory listing
Apache (.htaccess):Nginx :
Protect sensitive files
Apache (.htaccess):< FilesMatch "\.(ini|log|conf|sql)$" >
Require all denied
</ FilesMatch >
Set security headers
Apache (.htaccess):Header always set X-Frame- Options "DENY"
Header always set X-Content-Type- Options "nosniff"
Header always set X-XSS-Protection " 1 ; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Nginx :add_header X-Frame-Options "DENY" ;
add_header X-Content-Type-Options "nosniff" ;
add_header X-XSS-Protection "1; mode=block" ;
add_header Referrer-Policy "strict-origin-when-cross-origin" ;
Database Security
MySQL/MariaDB Configuration
Use dedicated database user
-- Create database user with limited privileges
CREATE USER ' refugio_app '@ 'localhost' IDENTIFIED BY 'strong_password_here' ;
-- Grant only necessary privileges
GRANT SELECT , INSERT , UPDATE , DELETE ON refugio_db. * TO 'refugio_app' @ 'localhost' ;
-- Do NOT grant DROP, CREATE, ALTER in production
FLUSH PRIVILEGES;
Regular backups
Set up automated database backups: # Example cron job (daily at 2 AM)
0 2 * * * mysqldump -u backup_user -p 'password' refugio_db | gzip > /backups/refugio_ $( date + \% Y \% m \% d ) .sql.gz
Restrict database access
-- Bind to localhost only (in my.cnf)
[mysqld]
bind - address = 127 . 0 . 0 . 1
File Upload Security
For profile photos (referenced in viewSocio.php):
Validate file types
The system already validates (from functions.php:1492): $formatos_permitidos = [ 'image/jpeg' , 'image/jpg' , 'image/png' , 'image/gif' ];
$extensiones_permitidas = [ 'jpg' , 'jpeg' , 'png' , 'gif' ];
Limit file size
Maximum 5MB is enforced (from functions.php:1494): $max_size = 5 * 1024 * 1024 ; // 5MB
Store uploads outside web root
Best practice: Store uploaded files outside the public web directory $upload_dir = '/var/uploads/refugio/photos/' ;
// Serve files through a PHP script that validates access
Sanitize filenames
$filename = preg_replace ( '/[^a-zA-Z0-9._-]/' , '' , $filename );
$filename = uniqid () . '_' . $filename ; // Prevent collisions
Monitoring and Auditing
Enable Logging
Implement comprehensive logging:
// Log authentication attempts
function log_auth_attempt ( $email , $success , $ip ) {
$status = $success ? 'SUCCESS' : 'FAILED' ;
error_log ( "[AUTH] $status login attempt for $email from $ip " );
}
// Log administrative actions
function log_admin_action ( $admin_id , $action , $details ) {
error_log ( "[ADMIN] User $admin_id performed $action : $details " );
}
Monitor for Security Issues
Security Monitoring
Failed login attempts : Monitor for brute force attacks
Unusual reservation patterns : Detect abuse or suspicious activity
Database errors : Watch for SQL injection attempts
File upload attempts : Monitor for malicious file uploads
Session anomalies : Detect session hijacking attempts
Regular Security Audits
Weekly tasks
Review authentication logs for failed attempts
Check for unusual user account activity
Monitor reservation patterns
Monthly tasks
Review user accounts and remove inactive ones
Update dependencies (PHP, web server, database)
Check for security updates
Review and rotate admin passwords
Quarterly tasks
Full security audit
Penetration testing
Review and update security policies
Test backup restoration procedures
Incident Response
If you suspect a security breach:
Immediate actions
Take the system offline if actively being attacked
Change all admin passwords immediately
Review access logs for unauthorized access
Check database for unauthorized modifications
Investigation
Identify the breach vector : How did the attacker gain access?
Assess the damage : What data was accessed or modified?
Document everything : Keep detailed notes for analysis
Remediation
Patch the vulnerability that allowed the breach
Restore from clean backups if data was compromised
Implement additional security measures
Notify affected users if their data was compromised
Prevention
Conduct post-incident review
Update security procedures based on lessons learned
Implement additional monitoring
Provide security training to administrators
Additional Security Recommendations
Rate Limiting
Implement rate limiting to prevent brute force attacks:
// Example rate limiting for login attempts
function check_rate_limit ( $ip ) {
$max_attempts = 5 ;
$time_window = 300 ; // 5 minutes
// Check attempts from IP in time window
// Implementation depends on your session/cache storage
// Return true if allowed, false if rate limited
}
Two-Factor Authentication (Future Enhancement)
Consider implementing 2FA for administrator accounts:
Use TOTP (Time-based One-Time Password)
Libraries: GoogleAuthenticator, etc.
Require for all admin logins
Implement Content Security Policy (CSP):
header ( "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' cdn.jsdelivr.net;" );
Regular Updates
Keep all software up to date:
PHP version
Web server (Apache/Nginx)
Database (MySQL/MariaDB)
Operating system security patches
Summary
Security is an ongoing process, not a one-time setup. Regular monitoring, updates, and adherence to these best practices will keep your Refugio system secure and protect your users’ data.
Key takeaways :
✅ Use HTTPS in production (mandatory)
✅ Implement CSRF protection
✅ Disable error display in production
✅ Use strong passwords and rotate regularly
✅ Monitor logs for suspicious activity
✅ Keep software updated
✅ Regular security audits
✅ Have an incident response plan
For technical implementation details, refer to the source code files referenced throughout this guide.