Hoy se ha establecido la obligatoriedad del ‘pase COVID’ en Euskadi para restaurantes y locales de ocio nocturno. Dado que planean ampliar la obligatoriedad a más actividades, ayer estuve indagando acerca de qué consistía este pase y cómo podía obtenerlo.
Como me puede la curiosidad, una vez había obtenido mi certificado, me puse a investigar cómo funcionaba la página web y el proceso de generar un certificado en PDF. Lo que encontré no fue poco.
La motivación de publicar este post no es solamente mostrar lo fácil que era para cualquiera con un mínimo de conocimientos en informática acceder a información personal ajena, sino también denunciar la ineptitud y la (probable) impunidad de los responsables de un fallo tan monumental.
¿Qué implicaban estas vulnerabilidades?
Mediante las múltiples vulnerabilidades que encontré en la página web, se podían obtener los siguientes datos de cualquier persona que estuviese registrada en la base de datos de Osakidetza (es decir, todo residente en Euskadi):
- Nombre y apellidos
- Fecha de nacimiento
- NIF
- Número de teléfono
- Número TIS (Tarjeta Individual Sanitaria)
- CIC (Código de Identificación Corporativo)
- Certificado de vacunación digital:
- Código QR
- Nombre de la vacuna administrada
- Número de dosis administradas
- Fecha de última vacunación
- Certificado de recuperación: documento certificatorio de haber superado la enfermedad tras haber tenido PCR positiva.
- Certificado de prueba negativa: documento certificatorio de prueba PCR negativa.
Nada más encontré estas vulnerabilidades, avisé de ello a un contacto que pudo hacer llegar la información a los responsables de esta página web. Hoy al mediodía han solucionado las vulnerabilidades, por eso procedo a publicar este post.
¿Desde cuándo estaban presentes estas vulnerabilidades?
Para intentar descubrir desde cuándo estaban presentes estas vulnerabilidades en la página web, he buscado las capturas en la Wayback Machine de Internet Archive. La captura más antigua que se ha realizado es del 22 de junio de 2021. El código fuente vulnerable está presente en esta captura, por lo que, al menos desde esa fecha, cualquier persona podía acceder a todos los datos que he listado.
¿Dónde estaban presentes estas vulnerabilides?
Las vulnerabilidades se encontraban en las páginas web de Osakidetza para la generación de certificados relacionados con el COVID. Esta página web de euskadi.eus contiene los enlaces a los distintos métodos para identificarse y acceder a los certificados.
Se ofrecen tres métodos para identificarse:
- Mediante identificación electrónica (BakQ y otros certificados digitales)
- TIS + Fecha de nacimiento + Primer apellido + Código de verificación SMS
- DNI + Fecha de nacimiento + Primer apellido + Código de verificación SMS
Los métodos 2 y 3 fracasaban al llevar a cabo su cometido, que en teoría es verificar que cada usuario solamente pueda acceder a los datos que le pertenecen.
La generación de certificados en PDF también era deficiente, ya que no solo permitía generar los certificados a partir de tus datos, sino a partir de los de cualquier otro.
En los siguientes apartados explico lo sencillo que era esquivar los sistemas de “seguridad” que se estaban utilizando en la página.
Obtener el certificado de vacunación de cualquier ciudadano de Euskadi
Después de pasar el proceso de identificación con cualquiera de los métodos, accedes a la página donde puedes generar el certificado de vacunación en PDF.
El código fuente de la página contenía las siguientes líneas:
<!-- Filtra la tabla de Nombres comerciales por el idPersona -->
<div id="GRID_CertificadoCVD_filter_div" class="collapse">
<form id="GRID_CertificadoCVD_filter_form">
<div id="GRID_CertificadoCVD_filter_toolbar">
<input id="idPersona" type="hidden" value="xxxxxx">
</div>
</form>
</div>
El valor del input oculto #idPersona
contenía un número identificativo único
por persona. Lo lógico sería que este código estuviese simplemente para realizar
lógica de la parte del navegador. Pero al momento de pulsar en el botón de
generar un certificado, la llamada que se hacía al servidor enviaba el valor que
tuviese ese input y elegía los datos de la persona a partir ese número.
Indicando cualquier número dentro de cierto rango, accedías al certificado de la persona que tuviese ese número identificativo. No era muy difícil intuir que los posibles valores de ese número eran 000001, 000002, 000003, … hasta la cantidad de personas registradas en el sistema (es decir, que parecía un número autoincrementado de la base de datos). Un cibercriminal podría haber automatizado fácilmente la generación de certificados para todas las personas de Euskadi con un simple script.
Es relevante mencionar que los certificados de vacunación COVID contienen (al menos) la siguiente información sobre la persona:
- Nombre completo
- Fecha de nacimiento
- Fabricante de la vacuna administrada
- Número de dosis
- Fecha de vacunación
Identificarse como cualquier persona y obtener todos sus datos
Mediante la página de identificación en la que se te pide indicar el DNI, se podía obtener TODOS los datos que he listado al comienzo del post, saltándote la verificación por SMS.
Primero explico el procedimiento en caso de conocer el DNI, fecha de nacimiento y primer apellido de la persona, y posteriormente explicaré como con tan solo el TIS podías conseguir el mismo resultado.
Introducías los datos en el formulario:
Y al pasar al siguiente paso, se te informaba de que se iba a enviar un código de verificación mediante un SMS al número de teléfono que tuviese asociado a tu persona:
Parece todo muy seguro: para verificar que es la persona correcta envían un SMS a un teléfono que solo esa persona tiene acceso. Y por si fuera poco, censuran parte del número de teléfono para que, en caso de que alguien hubiese llegado hasta este punto del proceso, no pudiese obtener el número de teléfono completo de la persona. Pues todo lo contrario.
De forma similar al #idPersona
del apartado anterior, el número de teléfono
completo, sin censurar, se había cargado a un input oculto del código fuente.
Pero lo peor no es eso. Podías modificar este input, introduciendo el número de
teléfono que quisieras, y el sistema enviaba el SMS de verificación
a ese número.
En este paso del proceso también se cargaban en inputs ocultos del código fuente el TIS y CIC de la persona.
El último paso del procedimiento, introducir el código recibido en el SMS:
Y finalmente accedías a la página de generación de certificados.
En caso de que no tuvieses los datos del primer paso del formulario (DNI, fecha de nacimiento y primer apellido), podías saltarte el procedimiento igualmente, utilizando el TIS de la persona. Dado que el TIS es un simple número de 8 dígitos, también se podía probar con TIS aleatorios, que seguramente iban a pertenecer a alguien.
La forma de saltarse el procedimiento de los datos del formulario era ejecutar manualmente un código de JavaScript que enviara la petición de generar un código de verificación por SMS. Este código solo requería del TIS y del número de teléfono al que enviar el código (en el código fuente se puede ver que también se envía el CIC y el DNI, pero estos se ignoraban en el proceso de validación).