Case study
Rodak — Rescate, seguridad y migración de un e-commerce Rodak — Rescue, security, and migration of an e-commerce site
Una tienda WooCommerce con 1.186 pedidos reales que venía de un compromiso de seguridad. El cliente preguntó si el backup servía, y lo contesté con un ensayo real, no con un "debería andar". A WooCommerce store with 1,186 real orders coming off a security compromise. The client asked whether the backup actually worked, and I answered with a real rehearsal, not with "it should".
Contexto Context
Rodak es una mueblería que vende online. Me contrataron para reposicionar la marca y construir un configurador de escritorios, pero al abrir el sitio apareció otra cosa primero: una instalación comprometida, sobre hosting compartido con un MySQL viejo, y con la tienda facturando. No se podía rehacer de cero ni apagar: había que arreglarlo en movimiento. Rodak is a furniture company selling online. They hired me to reposition the brand and build a desk configurator, but opening the site something else surfaced first: a compromised installation, on shared hosting with an old MySQL, and with the store still taking orders. Rebuilding from scratch or shutting it down were both off the table: it had to be fixed while running.
Problema Problem
Antes de cualquier migración el cliente hizo la pregunta correcta: con el backup que tenemos, ¿estás 100% seguro de que en otro servidor podemos desplegar la misma página, idéntica? Esa pregunta no se contesta leyendo un archivo. Un backup no verificado no es un backup: es un archivo grande. Before any migration the client asked the right question: with the backup we have, are you 100% sure we can deploy the same site on another server, identical? You do not answer that by reading a file. An unverified backup is not a backup: it is a large file.
Cómo lo resolví How I solved it
- Levanté un clon aislado del servidor con tres capas de protección — autenticación básica, cuarentena de red y noindex — para poder trabajar con datos reales sin exponer nada.
- Restauré el backup completo, en 14 partes, del lado del servidor, y verifiqué el SHA-256 de las 14 antes de importar nada.
- Definí gates numéricos ANTES de empezar y después expliqué cada delta: 144/144 tablas importadas, 1.186 pedidos = 1.181 previos + 5 nuevos con sus fechas, 322 variaciones exactas, 1.006 archivos de medios, 20.310 archivos de plugins contra 20.310.
- El smoke test lleva controles positivos y negativos: home y tienda responden 200, una URL inventada responde 404, y hay 0 referencias al dominio viejo — con un control positivo de 176 coincidencias que demuestra que la búsqueda funcionaba.
- Para la seguridad armé un ledger donde cada componente solo se cierra con un estado terminal: corregido, eliminado con ruta verificada, o excepción escrita del dueño. "El scanner no lo detecta" no es un estado.
- Crucé las CVEs de cada componente contra fuentes públicas y dejé anotada la limitación: una de las APIs que quería usar como segunda fuente independiente fue retirada, así que el cruce quedó con una sola fuente y eso está declarado, no escondido.
Mi rol My role
Auditoría, respuesta al incidente, plan y ejecución del backup y del ensayo de restore, y la comunicación con el cliente. Buena parte del trabajo fue traducir todo esto a mensajes que el dueño pudiera leer sin ser técnico, sin bajarle el rigor a lo que había abajo. Audit, incident response, planning and executing the backup and the restore rehearsal, and client communication. A good part of the job was translating all of this into messages the owner could read without being technical, without watering down the rigor underneath.
Resultado Result
El ensayo dio verde en todos los gates: la migración a otro servidor quedó probada, no prometida. Además apareció algo que nadie estaba buscando — una limpieza previa había borrado 20 usuarios, incluida la cuenta de administración del hosting — y lo levanté con la aritmética exacta que lo demostraba. Ese hallazgo salió del ensayo; sin ensayo, se descubría durante la migración real. The rehearsal came back green on every gate: migrating to another server was proven, not promised. It also surfaced something nobody was looking for — a previous cleanup had deleted 20 users, including the hosting admin account — and I raised it with the exact arithmetic that proved it. That finding came out of the rehearsal; without it, it would have surfaced during the real migration.
Aprendizajes Learnings
- Un backup se verifica por consistencia, contando filas restauradas, no por la existencia del archivo.
- Todo test necesita un control positivo. "0 referencias al dominio viejo" no prueba nada si la búsqueda estaba rota: el control de 176 coincidencias es lo que le da valor a ese 0.
- Declarar las limitaciones de una auditoría la hace más creíble, no menos.
- Frente a un cliente, un ensayo reproducible vale más que cualquier garantía verbal.