← Volver al blog

Auditamos la seguridad de nuestro propio servidor y encontramos cosas que no le perdonaríamos a un cliente

Daniel García·

Llevábamos meses metiendo cabeceras de seguridad y CSP en las webs de los clientes y nunca habíamos hecho lo mismo con la nuestra. Se nota cuando por fin te sientas a mirarlo: encontramos cosas que a un cliente le habríamos hecho corregir en la primera revisión.

La que más me hizo removerme en la silla fue el despliegue por SSH. El workflow de GitHub Actions usaba ssh-keyscan contra la IP del VPS cada vez que desplegábamos, sin comprobar esa clave contra nada. Eso es aceptar ciegamente la huella del servidor que responda en ese momento: si alguien intercepta la conexión con un ataque de intermediario justo cuando se ejecuta el pipeline, se lo traga sin rechistar. Lo arreglamos metiendo a mano la clave pública ED25519 real del VPS en el workflow y quitando el StrictHostKeyChecking=no que llevaba ahí desde que monté el despliegue, hace un par de semanas.

También nos faltaban cabeceras que llevamos meses recomendando a otros: X-Frame-Options, Strict-Transport-Security, un Content-Security-Policy de verdad. Las añadimos en un nginx.conf de 65 líneas que ahora se copia dentro de la imagen Docker en el build. Montar el CSP fue lo más pesado, no porque sea complicado sino porque hay que ir probando qué rompe: Google Fonts necesita su propio origen en style-src y font-src, Google Analytics necesita script-src y connect-src, y el formulario de contacto llama a la API de Web3Forms, así que sin meterla en connect-src el fetch fallaba en silencio y nadie se enteraba hasta que un cliente potencial decía que había escrito y no le habíamos contestado. Tuvimos que dejar unsafe-inline en script-src por las animaciones de scroll y el aviso de cookies, que van inline en el layout. No es la política más estricta que existe, pero es infinitamente mejor que no tener ninguna.

Pinchamos también las versiones de Node y de nginx en el Dockerfile. Antes tirábamos de alpine a secas, que un día te cambia de versión mayor sin avisar y el build se rompe sin que hayas tocado nada.

Hay una cosa que no se arregla con código y que se me había pasado por completo: la clave de acceso de Web3Forms estaba sin restringir a nuestro dominio. Cualquiera que la sacara del bundle de JavaScript, que es público, podía usarla para mandar formularios desde cualquier otra web y quemarnos la cuota. Eso solo se cambia a mano en el panel de Web3Forms, y sigue en mi lista de tareas mientras escribo esto.

Lo que más me incomoda no es ninguno de los fallos en sí, sino cuánto tiempo llevaban ahí sin que nadie los mirara. Auditamos la infraestructura de un cliente cuando entra un proyecto nuevo o cuando algo huele mal. La nuestra la montamos una vez, funcionó, y ahí se quedó. Sospecho que no somos la única agencia pequeña a la que le pasa esto con su propia casa.

seguridadservidordeployment