Saltar al contenido principal

Guía de Seguridad

Medidas de Seguridad Implementadas

1. Protección de Archivos

El plugin incluye múltiples capas de protección:

Archivos index.php

Todas las carpetas contienen un archivo index.php vacío que previene el listado de directorios.

Archivo .htaccess

Bloquea el acceso a:

  • Archivos de documentación (.md)
  • Archivos de configuración (composer.json, package.json)
  • Archivos de logs
  • Instalador (install.php) después de la instalación

2. Validación de Datos

TODAS las entradas de usuario se validan con SR_Validator:

// Ejemplo de validación
if ( ! SR_Validator::is_valid_email( $email ) ) {
return new WP_Error( 'invalid_email', 'Email no válido' );
}

if ( ! SR_Validator::is_required( $name ) ) {
return new WP_Error( 'missing_name', 'El nombre es obligatorio' );
}

Métodos disponibles:

  • is_required() - Campo obligatorio
  • is_valid_email() - Email válido
  • is_valid_phone() - Teléfono válido
  • is_valid_url() - URL válida
  • is_valid_nif() - NIF/CIF español
  • is_numeric() - Número válido
  • is_positive() - Número positivo
  • is_in_range() - Dentro de rango
  • Y más...

3. Sanitización de Datos

TODAS las entradas se limpian con SR_Sanitizer antes de guardar en BD:

// Ejemplo de sanitización
$clean_data = array(
'name' => SR_Sanitizer::sanitize_text( $input['name'] ),
'email' => SR_Sanitizer::sanitize_email( $input['email'] ),
'phone' => SR_Sanitizer::sanitize_phone( $input['phone'] ),
'price' => SR_Sanitizer::sanitize_price( $input['price'] ),
);

Métodos disponibles:

  • sanitize_text() - Texto plano
  • sanitize_email() - Email
  • sanitize_phone() - Teléfono
  • sanitize_price() - Precio/decimal
  • sanitize_url() - URL
  • sanitize_json() - JSON
  • sanitize_date() - Fecha
  • Y más...

4. Escape de Salida

TODAS las salidas HTML usan funciones de escape de WordPress:

// En las vistas
echo esc_html( $order->order_number );
echo esc_attr( $customer->name );
echo esc_url( $shop->website );
echo esc_textarea( $order->notes );

NUNCA hagas:

// ❌ INCORRECTO - Vulnerable a XSS
echo $user_input;
echo "<div>$variable</div>";

// ✅ CORRECTO
echo esc_html( $user_input );
echo '<div>' . esc_html( $variable ) . '</div>';

5. Nonces (CSRF Protection)

TODOS los formularios usan nonces:

// En el formulario
wp_nonce_field( 'sr_create_order', 'sr_order_nonce' );

// Al procesar
if ( ! isset( $_POST['sr_order_nonce'] ) ||
! wp_verify_nonce( $_POST['sr_order_nonce'], 'sr_create_order' ) ) {
wp_die( 'Error de seguridad' );
}

6. Verificación de Capabilities

TODAS las operaciones verifican permisos:

// Verificar permiso antes de la acción
if ( ! current_user_can( 'sr_edit_orders' ) ) {
wp_die( __( 'No tienes permiso para editar órdenes.', 'sistema-reparaciones' ) );
}

7. SQL Injection Prevention

TODAS las queries usan $wpdb->prepare():

// ✅ CORRECTO - Protegido
$order = $wpdb->get_row( $wpdb->prepare(
"SELECT * FROM {$table} WHERE id = %d",
$order_id
) );

// ❌ INCORRECTO - Vulnerable
$order = $wpdb->get_row( "SELECT * FROM {$table} WHERE id = {$order_id}" );

8. Protección de Acceso Directo

Todos los archivos PHP verifican contexto de WordPress:

// Al inicio de cada archivo PHP
if ( ! defined( 'ABSPATH' ) ) {
exit; // Salir si se accede directamente
}

9. Roles y Capabilities Granulares

El sistema usa capabilities específicas en lugar de roles genéricos:

// Capabilities específicas
'sr_view_orders'
'sr_create_orders'
'sr_edit_orders'
'sr_delete_orders'
'sr_view_customers'
'sr_create_customers'
// ... y más

Esto permite control fino de permisos.

10. Logs de Actividad

Los cambios importantes se registran en tablas de historial:

  • wp_sr_status_history - Cambios de estado de órdenes
  • wp_sr_stock_movements - Movimientos de inventario
  • wp_sr_notifications - Emails enviados

Checklist de Seguridad para Desarrollo

Si extiendes el plugin, SIEMPRE:

Al Recibir Datos del Usuario

  • Verificar nonce con wp_verify_nonce()
  • Verificar capability con current_user_can()
  • Validar datos con SR_Validator
  • Sanitizar datos con SR_Sanitizer

Al Guardar en Base de Datos

  • Usar $wpdb->prepare() para queries
  • Usar $wpdb->insert() o $wpdb->update() cuando sea posible
  • Nunca concatenar directamente variables en SQL

Al Mostrar Datos

  • Usar esc_html() para texto
  • Usar esc_attr() para atributos HTML
  • Usar esc_url() para URLs
  • Usar esc_js() para JavaScript
  • Usar esc_textarea() para textareas

En Formularios

  • Incluir wp_nonce_field()
  • Verificar nonce al procesar
  • Usar POST en lugar de GET para operaciones de escritura
  • No confiar en datos de $_REQUEST

En AJAX

  • Registrar action con wp_ajax_ y wp_ajax_nopriv_
  • Verificar nonce en cada request
  • Verificar capability
  • Sanitizar entrada
  • Escapar salida en JSON

Mejores Prácticas

1. Principio de Mínimo Privilegio

Asigna solo los permisos necesarios:

// ✅ Bueno - Capability específica
if ( current_user_can( 'sr_edit_orders' ) ) {
// Permitir edición
}

// ❌ Malo - Demasiado permisivo
if ( current_user_can( 'manage_options' ) ) {
// Solo para administradores
}

2. Validar en el Servidor

SIEMPRE valida en el servidor, aunque tengas validación en JavaScript:

// La validación JavaScript es solo UX
// La validación PHP es SEGURIDAD

if ( ! SR_Validator::is_valid_email( $email ) ) {
return new WP_Error( 'invalid_email', 'Email inválido' );
}

3. No Confiar en el Cliente

Nunca confíes en datos que vienen del cliente:

// ❌ Malo - Confiar en el cliente
$is_admin = $_POST['is_admin']; // El cliente puede mentir

// ✅ Bueno - Verificar en el servidor
$is_admin = current_user_can( 'manage_options' );

4. Logs de Seguridad

Registra eventos importantes:

// Log de inicio de sesión fallido
if ( ! $login_success ) {
error_log( 'Login fallido para usuario: ' . $username );
}

// Log de cambios críticos
do_action( 'sr_order_status_changed', $order_id, $old_status, $new_status );

5. Rate Limiting

Para operaciones sensibles, implementa límites:

// Ejemplo de rate limiting en AJAX
$transient_key = 'sr_ajax_limit_' . $user_id;
$count = get_transient( $transient_key );

if ( $count && $count > 10 ) {
wp_send_json_error( 'Demasiadas peticiones' );
}

set_transient( $transient_key, ( $count + 1 ), MINUTE_IN_SECONDS );

Vulnerabilidades Comunes a Evitar

1. SQL Injection

// ❌ VULNERABLE
$query = "SELECT * FROM table WHERE id = {$_GET['id']}";

// ✅ SEGURO
$query = $wpdb->prepare( "SELECT * FROM table WHERE id = %d", $_GET['id'] );

2. XSS (Cross-Site Scripting)

// ❌ VULNERABLE
echo "<h1>Bienvenido " . $_GET['name'] . "</h1>";

// ✅ SEGURO
echo '<h1>Bienvenido ' . esc_html( $_GET['name'] ) . '</h1>';

3. CSRF (Cross-Site Request Forgery)

// ❌ VULNERABLE - Sin nonce
if ( $_POST['delete'] ) {
delete_order( $_POST['id'] );
}

// ✅ SEGURO - Con nonce
if ( wp_verify_nonce( $_POST['nonce'], 'delete_order' ) ) {
delete_order( $_POST['id'] );
}

4. Directory Traversal

// ❌ VULNERABLE
$file = $_GET['file'];
include( "templates/{$file}.php" );

// ✅ SEGURO
$file = basename( $_GET['file'] ); // Elimina ../ y rutas
$allowed_files = array( 'template1', 'template2' );
if ( in_array( $file, $allowed_files ) ) {
include( "templates/{$file}.php" );
}

5. Remote Code Execution

// ❌ VULNERABLE - NUNCA uses eval()
eval( $_POST['code'] );

// ❌ VULNERABLE - NUNCA uses unserialize() con datos del usuario
$data = unserialize( $_POST['data'] );

// ✅ SEGURO - Usa json_decode()
$data = json_decode( $_POST['data'], true );

Checklist de Auditoría de Seguridad

Antes de lanzar a producción:

  • Todos los formularios tienen nonces
  • Todas las queries usan $wpdb->prepare()
  • Todos los outputs usan funciones de escape
  • Todas las operaciones verifican capabilities
  • Todas las entradas se validan y sanitizan
  • No hay eval() ni unserialize() de datos del usuario
  • Los archivos .md y .log están bloqueados
  • El instalador (install.php) está eliminado o bloqueado
  • Los directorios tienen archivos index.php
  • WP_DEBUG está deshabilitado en producción
  • Las credenciales no están en el código
  • Los errores no revelan información sensible

Mantenimiento de Seguridad

Actualizaciones Regulares

  1. WordPress: Mantener actualizado
  2. PHP: Usar versiones soportadas
  3. MySQL: Usar versiones recientes
  4. Plugin: Aplicar parches de seguridad

Backups

  • Backup diario de la base de datos
  • Backup semanal de archivos
  • Probar restauración periódicamente

Monitoreo

  • Revisar logs de error regularmente
  • Monitorear intentos de login fallidos
  • Vigilar cambios inesperados en archivos

Reporte de Vulnerabilidades

Si encuentras una vulnerabilidad de seguridad:

  1. NO la publiques públicamente
  2. Envía un reporte privado a: [correo de seguridad]
  3. Incluye:
    • Descripción de la vulnerabilidad
    • Pasos para reproducirla
    • Impacto potencial
    • Solución sugerida (si la tienes)

Certificación de Seguridad

El plugin Sistema de Gestión de Reparaciones implementa las mejores prácticas de seguridad de WordPress y ha sido revisado siguiendo las guías de OWASP y WordPress Security Team.

Fecha de última revisión: 2026-02-10