One Hat Cyber Team
Your IP :
104.23.243.196
Server IP :
104.21.51.23
Server :
Linux 128-201-239-36.cprapid.com 3.10.0-1160.41.1.el7.x86_64 #1 SMP Tue Aug 31 14:52:47 UTC 2021 x86_64
Server Software :
Apache
PHP Version :
7.4.33
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
home
/
juscatamarca
/
www
/
subdomains
/
escuela
/
admin
/
Edit File:
SEGURIDAD.md
# 🔒 GUÍA DE CONFIGURACIÓN DE SEGURIDAD - LOGIN ## Mejoras de Seguridad Implementadas El sistema de login ahora incluye las siguientes medidas de seguridad: ### 1. **Contraseñas Seguras con Bcrypt** - Reemplaza SHA256 con bcrypt (PASSWORD_BCRYPT) - Costo de hashing: 12 (protección contra GPU attacks) - Vulnerabilidad anterior: SHA256 es demasiado rápido y vulnerable ### 2. **Protección CSRF (Cross-Site Request Forgery)** - Token único por sesión generado aleatoriamente - Validación en cada POST - Previene ataques desde sitios externos ### 3. **Rate Limiting (Fuerza Bruta)** - Máximo 5 intentos fallidos en 15 minutos - Bloquea por usuario Y por IP - Limpieza automática de intentos antiguos ### 4. **Headers de Seguridad HTTP** ``` X-Content-Type-Options: nosniff - Previene MIME sniffing X-Frame-Options: DENY - Previene clickjacking X-XSS-Protection: 1; mode=block - Protección XSS del navegador Strict-Transport-Security - Fuerza HTTPS Content-Security-Policy - Política de recursos permitidos ``` ### 5. **Validación de Sesión Robusta** - Timeout de sesión: 1 hora - Validación de Strict SameSite cookies - Verificación de IP (previene session hijacking) - Regeneración de ID de sesión después de login ### 6. **Protección contra Session Fixation** - Regeneración de ID de sesión tras login exitoso - Validación de consistencia de IP - Timeout automático ### 7. **Logging de Seguridad** - Registro de intentos fallidos - Registro de logins exitosos - Auditoría de logout - IP y timestamp de cada evento ### 8. **Validación de Entrada Rigurosa** - Uso de prepared statements (PDO) - Validación de longitud de usuario (3-50 caracteres) - Validación de longitud de contraseña (max 100) - Sanitización de salida (htmlspecialchars) ### 9. **Opción "Recordar Usuario" Segura** - Solo guarda el nombre de usuario en cookie (NO la contraseña) - Cookie válida por 30 días - Se limpia al hacer logout - No es marcada como httpOnly (permite pre-llenar formulario) - Se elimina automáticamente si no se marca en próximo login ### 10. **Recuperación de Contraseña Segura** - Sistema de tokens por email o usuarios - Tokens únicos (64 caracteres, generados con random_bytes) - Expiración de tokens: 1 hora - Prevención de reutilización de tokens - Mensajes genéricos (sin revelar si usuario existe) - Flujo: 1. Usuario accede a `forgot-password.php` 2. Ingresa email o nombre de usuario 3. Sistema genera token único (expires_at = ahora + 1 hora) 4. Envía email con enlace: `reset-password.php?token=XXXXX` 5. Usuario hace clic en enlace 6. Valida token (no expirado, no usado) 7. Muestra formulario para nueva contraseña 8. Actualiza con bcrypt y marca token como usado ### 11. **Sin Credenciales Expuestas** - ✓ Eliminadas credenciales de prueba del HTML - ✓ Mensajes de error genéricos ("Credenciales incorrectas") - ✓ Sin información que revele si el usuario existe ### 12. **Organización de CSS en archivo externo** - Todo el CSS inline de las pantallas de login y dashboard fue movido a `assets/css/admin.css` - Esto permite eliminar `'unsafe-inline'` de `style-src` del CSP y simplificar el markup - Facilita reutilizar estilos y ajustar el diseño sin tocar PHP/HTML - Mejora la carga al permitir caché del archivo de estilos --- ## ⚙️ CONFIGURACIÓN INICIAL ### Paso 1: Crear Tablas de Seguridad ```bash # Acceder a la ruta: http://localhost/ecj%20web/admin/config/security-setup.php # O ejecutar directamente en PHP: php admin/config/security-setup.php ``` Esto crea: - `login_attempts`: Registro de intentos fallidos - `login_logs`: Auditoría de logins/logouts - `password_reset_tokens`: Tokens para recuperación de contraseña ### Paso 2: Actualizar Contraseñas a Bcrypt ```bash # Acceder a: http://localhost/ecj%20web/admin/config/update-password.php # Ingresar cada usuario y su nueva contraseña segura ``` **⚠️ IMPORTANTE:** Todas las contraseñas deben actualizarse a bcrypt. Las antiguas en SHA256 no funcionarán. ### Paso 3: Cambiar Contraseña de Admin 1. Acceder a `update-password.php` 2. Usuario: `admin` 3. Ingresa una contraseña fuerte (mínimo 8 caracteres) 4. Confirma Ejemplo de contraseña segura: - `Ecj@2024Admin!` - `Jud1c1al_Segura.2024` ### Paso 4: Crear Usuarios Adicionales (Opcional) ```sql INSERT INTO usuarios (usuario, nombre, apellido, password, estado) VALUES ( 'usuario1', 'Juan', 'Pérez', '$2y$12$...bcrypt_hash...', 'activo' ); ``` ### Paso 5: Configurar Recuperación de Contraseña (Opcional) #### En Desarrollo: - El sistema usa fallback a sesión si el email no se envía - Puedes usar la contraseña reset sin configurar email #### En Producción (Con Email Real): **Opción A: PHP mail() (Requiere servidor configurado)** - Asegurate que el servidor tiene `sendmail` configurado - Verifica en `php.ini`: directives `sendmail_path`, `SMTP`, `smtp_port` **Opción B: SMTP seguro (Recomendado)** Edita el archivo `admin/forgot-password.php` línea ~90: ```php // Reemplaza la sección mail() con esto: $mail = new PHPMailer(true); try { $mail->isSMTP(); $mail->Host = 'smtp.gmail.com'; // Servidor SMTP $mail->SMTPAuth = true; $mail->Username = 'tu_email@gmail.com'; // Tu email $mail->Password = 'app_password'; // Contraseña de app (Gmail necesita) $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; $mail->Port = 587; $mail->setFrom('tu_email@gmail.com', 'ECJ'); $mail->addAddress($email); $mail->Subject = 'Recuperar Contraseña - ECJ'; $mail->Body = $mensaje; $mail->send(); $email_sent = true; } catch (Exception $e) { // Fallback a sesión $_SESSION['password_reset_token'] = $token; } ``` **Para Gmail:** 1. Habilita "Acceso de apps menos seguras": https://myaccount.google.com/lesssecureapps 2. O genera "Contraseña de app": https://myaccount.google.com/apppasswords 3. Usa `composer require phpmailer/phpmailer` si aún no instalado #### Pruebas sin Email: 1. Accede a `admin/forgot-password.php` 2. Ingresa email o usuario 3. La sesión guardará un token en `$_SESSION['password_reset_token']` 4. Manualmente construye la URL: `reset-password.php?token=VALOR_DEL_TOKEN` 5. Prueba el reset de contraseña --- ## 🔑 Generación de Hash Bcrypt Si necesitas generar hashes manualmente (en desarrollo): ```php <?php // Generar hash $password = 'MiContraseña123!'; $hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]); echo $hash; // $2y$12$... // Verificar hash if (password_verify('MiContraseña123!', $hash)) { echo "Contraseña correcta"; } ?> ``` --- ## 📋 Recomendaciones de Seguridad Adicionales ### Para Producción: 1. **HTTPS Obligatorio** - Instalar certificado SSL/TLS - Generar certificados Let's Encrypt gratuitos - Forzar redirección HTTP → HTTPS 2. **Variables de Entorno** ```php // Usar .env en lugar de código DB_HOST=localhost DB_USER=... DB_PASS=... ``` 3. **Dos Factores (2FA) - Opcional** - Agregar TOTP (Time-based One-Time Password) - SMS codes - Email verification 4. **Auditoría Avanzada** - Guardar cambios de usuario/contraseña - Registrar acciones administrativas - Alertas de login desde IPs nuevas 5. **Rotación de Contraseñas** - Forzar cambio cada 90 días - Prevenir reutilización de últimas 3 contraseñas 6. **Backup de Base de Datos** - Realizar backups diarios - Almacenar en ubicación segura 7. **Monitoreo de Intentos** - Revisar `login_attempts` regularmente - Alertar de patrones sospechosos --- ## 🧪 Pruebas de Seguridad ### Test 1: Fuerza Bruta Bloqueada ``` Intentar login con contraseña incorrecta 5+ veces Esperado: "Demasiados intentos fallidos" ``` ### Test 2: Token CSRF ``` Modificar token CSRF en formulario Esperado: "Token de seguridad inválido" ``` ### Test 2b: Recordar Usuario ``` 1. Marcar "Recordar mi usuario" y hacer login Esperado: Usuario guardado en cookie por 30 días 2. Cerrar navegador y reabrir login.php Esperado: Campo de usuario pre-llenado 3. Hacer logout Esperado: Cookie de usuario eliminada, campo vacío en próxima carga ``` ### Test 3: Inyección SQL ``` Usuario: admin' OR '1'='1 Esperado: "Credenciales incorrectas" (SIN error SQL) ``` ### Test 4: Timeout de Sesión ``` Login y esperar 1 hora sin actividad Esperado: Redirección a login.php con ?timeout=1 ``` ### Test 5: IP Spoofing ``` Cambiar IP de sesión activa Esperado: Redirección a login.php con ?security=1 ``` ### Test 6: Recuperación de Contraseña ``` Paso 1: Ir a forgot-password.php Paso 2: Ingresar email o usuario válido Esperado: Mensaje genérico "Si la cuenta existe, recibirás un email" Paso 3: Copiar token de sesión ($_SESSION['password_reset_token']) Paso 4: Ir a reset-password.php?token=XXXXX Esperado: Formulario para nueva contraseña Paso 5: Ingresar nueva contraseña y confirmar Esperado: "Contraseña actualizada exitosamente" Paso 6: Intentar reutilizar el mismo token Esperado: "Token inválido o expirado" Paso 7: Generar nuevo token e intentar usar después de 1 hora Esperado: "Token expirado" ``` --- ## 📊 Monitoreo Revisar regularmente los logs de seguridad: ```sql -- Intentos fallidos recientes SELECT usuario, COUNT(*) as intentos, MAX(timestamp) as ultimo FROM login_attempts WHERE timestamp > DATE_SUB(NOW(), INTERVAL 1 DAY) GROUP BY usuario, ip ORDER BY intentos DESC; -- Logins exitosos SELECT u.nombre, l.ip, l.timestamp FROM login_logs l JOIN usuarios u ON l.user_id = u.id WHERE l.action = 'login' ORDER BY l.timestamp DESC LIMIT 20; ``` --- ## ⚠️ Errores Comunes ### "Token de seguridad inválido" - Cause: Sesión expirada o token regenerado - Solución: Recargar página y volver a intentar ### "Demasiados intentos fallidos" - Cause: 5+ intentos fallidos en 15 minutos - Solución: Esperar 15 minutos o usar otra IP/usuario ### "La sesión expiró" - Cause: Inactividad por más de 1 hora - Solución: Volver a hacer login ### Hash no funciona después de actualizar - Cause: Contraseña en SHA256, cambiar a bcrypt - Solución: Ejecutar `update-password.php` --- ## 📝 Registro de Cambios **v1.0 - 2024** - ✓ Bcrypt en lugar de SHA256 - ✓ Protección CSRF - ✓ Rate limiting - ✓ Headers de seguridad - ✓ Validación de sesión mejorada - ✓ Logging de seguridad - ✓ Regeneración de ID de sesión - ✓ Recuperación de contraseña por email con tokens - ✓ Opción "Recordar usuario" segura - ✓ CSS en archivo externo --- ## SEO y Social Sharing - Añadido `robots.txt` para impedir indexación de `/admin/` y `/aulavirtual/`. - Todas las páginas del panel administrativo envían el header `X-Robots-Tag: noindex, nofollow` (vía `admin/config/functions.php`). - Páginas públicas principales (`index.html`, `cursos.html`) incluyen meta Open Graph y Twitter Card apuntando al logo oficial como miniatura para compartir en redes. Consejo de pruebas: 1. Verifica `robots.txt`: `https://tu-dominio/robots.txt` debe listar `Disallow: /admin/`. 2. Verifica response headers de una página admin (por ejemplo `admin/dashboard.php`) y busca `X-Robots-Tag: noindex, nofollow`. 3. Prueba el depurador de Facebook: https://developers.facebook.com/tools/debug/ para ver cómo se renderiza la tarjeta compartida.
Simpan