Inteligencia de vulnerabilidades
CVSS explicado: cómo leer y calcular una vector string
Qué significa una puntuación CVSS como 9.8, cómo se construyen las vector strings de v4.0 y v3.1 y cómo decodificar y recalcular una a mano.
Un registro CVE nombra la falla y apunta al proveedor, que es quien define la versión corregida.
Lees una noticia que dice que una falla con número CVE se está explotando. Diez minutos después, un colega te pregunta si ya estás parcheado. El número es el único dato en el que ambos coinciden. Da nombre a una falla. No te dice qué tan grave es esa falla para tus sistemas, qué versiones tuyas están afectadas ni qué instalar.
Este artículo explica qué es un ID CVE, quién lo asigna, qué significa cada campo de un registro CVE y cómo la National Vulnerability Database (NVD) complementa ese registro. La parte práctica lee un registro muy conocido, el CVE-2021-44228 (Log4Shell), campo por campo, primero desde cve.org y luego desde la API de la NVD. Después abre el aviso del proveedor al que apunta el registro. Lo principal que hay que recordar: el registro CVE te lleva al aviso del proveedor, y el aviso del proveedor es la fuente de verdad sobre las versiones corregidas.
Si ya leíste Qué es una vulnerabilidad, los términos te van a sonar conocidos. El laboratorio hace solo consultas de lectura a dos servicios públicos y a una página web pública.
CVE significa Common Vulnerabilities and Exposures. El CVE Program, como lo describe su propia descripción general, identifica, define y cataloga vulnerabilidades de ciberseguridad divulgadas públicamente. Cada vulnerabilidad recibe una entrada, llamada registro CVE, y el ID es el identificador de esa entrada. Tiene la forma CVE-AÑO-NÚMERO. El año es el año en que se reservó el ID, que muchas veces no coincide con el año en que se escribió o se corrigió el error.
El ID es un nombre. Permite que dos personas, o dos herramientas, digan "esta" y se refieran a la misma falla. No lleva puntaje de severidad, lista de productos afectados, parche ni estado de explotación. Eso está en el registro, y parte de la información viene de otras organizaciones.
El CVE Program trabaja a través de los CVE Numbering Authorities, o CNA. El sitio del CVE describe a los CNA como proveedores, investigadores, proyectos de código abierto, CERT, servicios alojados, proveedores de programas de recompensas por errores y consorcios. Cada uno está autorizado a asignar IDs y publicar registros dentro de su propio alcance. Cuando revisamos la página de CNA el 2026-11-08, figuraban 564 CNA, incluidos 3 CNA-LR (CNA de último recurso, para productos que ningún otro CNA cubre). La cifra cambia, así que consulta la página para el número actual.
Alcance es la palabra que conviene retener. La Apache Software Foundation es el CNA de los proyectos Apache, por eso el registro del CVE-2021-44228 la nombra como CNA. El CNA escribe el título, la descripción, los productos afectados, las referencias y los tipos de problema. Otras partes pueden agregar datos después, y ahí entra la NVD.
Los nombres de campo que siguen vienen del formato JSON de registros CVE. La vista JSON en cve.org y el JSON de la API de CVE usan la misma estructura.
El estado indica si la entrada está vigente. El registro de este laboratorio muestra "state": "PUBLISHED". También existen registros rechazados, así que verifica el estado antes que nada.
El JSON del CVE trae tres fechas: dateReserved, datePublished y dateUpdated. Para el CVE-2021-44228 son 2021-11-26, 2021-12-10 y 2025-10-21. La NVD mantiene sus propias fechas. Su campo published es 2021-12-10, y su lastModified es 2026-08-11 en la respuesta que obtuvimos. La página de cve.org muestra una fecha "Updated" aparte, 2023-04-03, que viene de los metadatos del proveedor (el CNA). Tres fuentes, tres fechas de actualización. Compáralas antes de dar por hecho que tienes el texto más reciente.
La descripción es el texto que escribe el CNA. Debe decir qué es la falla, qué la dispara y qué versiones alcanza. La descripción de Log4Shell indica el rango de versiones afectadas, nombra la función involucrada (búsquedas JNDI en la configuración, en mensajes de log y en parámetros), dice desde cuándo ese comportamiento quedó desactivado por defecto y afirma que log4net y otros proyectos de logging de Apache no están afectados. Esa última frase evita una tarde entera parcheando lo que no era.
Este bloque es la parte más útil del registro y la más fácil de leer mal. Cada afirmación de versión indica si un rango está afectado, no afectado o es desconocido, y puede expresar cambios en números de versión concretos.
La página de cve.org muestra la entrada de Log4j2 como una línea de tiempo: afectado desde 2.0-beta9, no afectado desde 2.3.1, afectado desde 2.4, no afectado desde 2.12.2, afectado desde 2.13.0 y no afectado desde 2.15.0. Una versión toma el estado del punto de cambio más reciente que la precede. Los huecos son lo importante. "Todo lo anterior a 2.15.0 es vulnerable" es incorrecto aquí, porque 2.3.1 y 2.12.2 aparecen como no afectados.
El campo lessThan nombra el componente, log4j-core*. El aviso de Apache dice que una aplicación que usa solo el JAR log4j-api no está afectada. Lee el componente junto con la versión. Además, la lista solo es tan completa como la que hizo el CNA. Los productos que incluyen la biblioteca pueden faltar, y ahí es donde ayudan el aviso del proveedor y los datos de configuración de la NVD.
Las referencias son enlaces a avisos de proveedores, listas de correo, textos de terceros y, a veces, páginas sobre explotación. La página de cve.org lista 53 referencias para el CVE-2021-44228, cada una con una etiqueta como vendor-advisory, mailing-list, third-party-advisory o exploit. Lee primero los enlaces vendor-advisory. Las páginas de terceros aportan contexto, no versiones corregidas. La copia de la NVD de este registro guarda las referencias en su propio orden, y sus cinco primeras son páginas de Packet Storm.
CWE es la Common Weakness Enumeration, un catálogo de tipos de debilidad. CWE-20 es Improper Input Validation (validación de entrada inadecuada), y CWE-502 es Deserialization of Untrusted Data (deserialización de datos no confiables). Un CWE dice qué tipo de error llevó a la falla. No nombra un producto.
El CNA lista CWE-20, CWE-400 y CWE-502. El registro de la NVD lista los mismos tres, atribuidos a la dirección de seguridad de Apache, y agrega CWE-917, atribuido a la propia NVD. Mantén visible la columna de la fuente. Puedes no estar de acuerdo con la asignación de un analista, y conviene saber cuál estás leyendo. CWE también sirve para agrupar. Una búsqueda por CWE encuentra todas las fallas de deserialización entre productos, lo que ayuda en revisión de código y en modelado de amenazas.
Las métricas guardan puntajes y valoraciones de distintas fuentes.
CVSS (Common Vulnerability Scoring System) da un puntaje base de 0 a 10, una etiqueta de severidad y una cadena vectorial que enumera los datos de entrada: vector de ataque, complejidad, privilegios, interacción del usuario, alcance e impacto. La entrada CVSS v3.1 de la NVD para este registro es 10.0, CRITICAL, con el vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H. El registro también tiene un puntaje CVSS v2.0 de la NVD, 9.3. El puntaje describe la falla bajo supuestos declarados. No describe tu exposición.
SSVC es un método de decisión que pregunta si la explotación está activa, si el ataque se puede automatizar y qué tan grande es el impacto técnico. Este registro tiene una entrada SSVC de una fuente coordinadora de CISA que marca explotación activa, automatizable sí e impacto técnico total.
KEV es el catálogo Known Exploited Vulnerabilities de CISA. El registro muestra una fecha de inclusión (2021-12-10), una fecha límite de acción (2021-12-24) y una acción requerida: aplicar las actualizaciones o retirar los activos afectados de la red. KEV significa que se observó explotación. Es una pregunta distinta de qué tan severa es la falla.
Las métricas cambian. Lee la fuente y la fecha junto con cada número.
La NVD la dirige el NIST, un proyecto separado del CVE Program. Toma los registros CVE y agrega lo que el CNA quizá no proporcionó: puntajes CVSS que calcula o confirma, mapeo de CWE, configuraciones CPE (coincidencias de producto y versión legibles por máquina), etiquetas de referencia y un campo de estado. La API de la NVD en services.nvd.nist.gov sirve esos registros enriquecidos. La página del panel de la NVD está junto a la documentación de la API, así que revísala para ver avisos antes de dar por hecho que el enriquecimiento está al día.
El bloque de configuración es la parte que casi nadie abre. Este registro tiene 20 bloques de configuración con 396 entradas de coincidencia CPE. La primera entrada es un paquete de firmware de Siemens, lo que muestra que la lista cubre productos que incluyen la biblioteca, no solo las versiones propias de Apache. Una configuración vacía o escasa puede significar que el análisis no terminó, no que el producto esté seguro.
El estado aquí es Analyzed. Eso significa que la NVD procesó el registro. No significa que la NVD haya probado algo en tu red. La fecha lastModified es 2026-08-11, mucho después de la publicación, así que un registro que leíste el año pasado puede haber cambiado.
Requisitos. Un navegador, curl (Git Bash en Windows ya lo incluye) y Python 3.12. jq es opcional. Todas las solicitudes de este laboratorio son lecturas de servicios públicos. No pongas en bucle la API de la NVD. Sin clave de API, la NVD limita las solicitudes en un período corto, así que ejecuta cada comando una vez.
Abre https://www.cve.org/CVERecord?id=CVE-2021-44228 y léela de arriba abajo. El día en que se hizo este laboratorio, mostraba:
El comando del laboratorio, escrito para jq:
curl -s 'https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2021-44228' | jq '.vulnerabilities[0].cve | {id, published, descriptions: .descriptions[0].value, weaknesses, references: [.references[0:5][].url]}'jq no estaba instalado en la máquina donde se probó este laboratorio, así que el mismo filtro se ejecutó en Python 3.12. Usa este si tampoco tienes jq:
curl -s 'https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2021-44228' -o nvd.json
python -c "import json; c=json.load(open('nvd.json', encoding='utf8'))['vulnerabilities'][0]['cve']; print(json.dumps({'id': c['id'], 'published': c['published'], 'descriptions': c['descriptions'][0]['value'], 'weaknesses': c['weaknesses'], 'references': [r['url'] for r in c['references'][0:5]]}, indent=2, ensure_ascii=False))"Salida observada de ese comando:
{
"id": "CVE-2021-44228",
"published": "2021-12-10T10:15:09.143",
"descriptions": "Apache Log4j2 2.0-beta9 through 2.15.0 (excluding security releases 2.12.2, 2.12.3, and 2.3.1) JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled. From log4j 2.15.0, this behavior has been disabled by default. From version 2.16.0 (along with 2.12.2, 2.12.3, and 2.3.1), this functionality has been completely removed. Note that this vulnerability is specific to log4j-core and does not affect log4net, log4cxx, or other Apache Logging Services projects.",
"weaknesses": [
{
"source": "[email protected]",
"type": "Secondary",
"description": [
{ "lang": "en", "value": "CWE-20" },
{ "lang": "en", "value": "CWE-400" },
{ "lang": "en", "value": "CWE-502" }
]
},
{
"source": "[email protected]",
"type": "Secondary",
"description": [
{ "lang": "en", "value": "CWE-917" }
]
}
],
"references": [
"http://packetstormsecurity.com/files/165225/Apache-Log4j2-2.14.1-Remote-Code-Execution.html",
"http://packetstormsecurity.com/files/165260/VMware-Security-Advisory-2021-0028.html",
"http://packetstormsecurity.com/files/165261/Apache-Log4j2-2.14.1-Information-Disclosure.html",
"http://packetstormsecurity.com/files/165270/Apache-Log4j2-2.14.1-Remote-Code-Execution.html",
"http://packetstormsecurity.com/files/165281/Log4j2-Log4Shell-Regexes.html"
]
}Fíjate en tres cosas. El published de la NVD trae una hora, 10:15, sin zona horaria, mientras que el JSON del CNA da medianoche del mismo día. La entrada CWE que agregó la NVD aparece en un bloque aparte. Y las cinco primeras referencias son páginas de terceros, así que el enlace del proveedor tiene que venir de un paso posterior.
python -c "import json; c=json.load(open('nvd.json', encoding='utf8'))['vulnerabilities'][0]['cve']; print('lastModified', c['lastModified'], '| vulnStatus', c['vulnStatus']); [print(k, m['source'], m['type'], m['cvssData']['version'], m['cvssData']['baseScore'], m['cvssData'].get('baseSeverity'), m['cvssData']['vectorString']) for k in ('cvssMetricV31', 'cvssMetricV2') for m in c['metrics'][k]]"Salida observada:
lastModified 2026-08-11T19:33:44.513 | vulnStatus Analyzed
cvssMetricV31 [email protected] Primary 3.1 10.0 CRITICAL CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
cvssMetricV31 134c704f-9b21-4f2e-91b3-4a467353bcc0 Secondary 3.1 10.0 CRITICAL CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
cvssMetricV2 [email protected] Primary 2.0 9.3 None AV:N/AC:M/Au:N/C:C/I:C/A:CLa entrada v2 no tiene etiqueta de severidad, lo cual es normal en CVSS v2. La fuente secundaria v3.1 es un identificador, no un nombre. El mismo identificador aparece en los datos SSVC junto al rol de coordinador de CISA, así que puedes inferir más de lo que dice el campo. Anota lo que puedes confirmar y di qué parte es inferencia.
curl -s 'https://cveawg.mitre.org/api/cve/CVE-2021-44228' -o cve5.json
python -c "import json; d=json.load(open('cve5.json', encoding='utf8')); print(json.dumps(d['cveMetadata'], indent=2))"Salida observada:
{
"state": "PUBLISHED",
"cveId": "CVE-2021-44228",
"assignerOrgId": "f0158376-9dc2-43b6-827c-5f631a4d8d09",
"assignerShortName": "apache",
"dateUpdated": "2025-10-21T23:25:23.121Z",
"dateReserved": "2021-11-26T00:00:00.000Z",
"datePublished": "2021-12-10T00:00:00.000Z"
}El campo assignerShortName identifica al CNA. El bloque de métricas del propio CNA no tiene puntaje CVSS, solo una entrada other que dice critical. El puntaje CVSS que ves viene de la NVD.
Abre https://logging.apache.org/log4j/2.x/security.html. La página redirige a logging.apache.org/security.html. Tiene una sección por CVE. La sección del CVE-2021-45046 aparece por encima de la del CVE-2021-44228.
En el texto que obtuvimos el 2026-11-08, la sección del CVE-2021-44228 da el rango afectado como [2.0-beta9, 2.3.1), [2.4, 2.12.2) y [2.13.0, 2.15.0), y las versiones corregidas como 2.3.1 para Java 6, 2.12.2 para Java 7 y 2.15.0 para Java 8 o superior. La sección del CVE-2021-45046 indica que la corrección del CVE-2021-44228 en la 2.15.0 quedó incompleta en algunas configuraciones no predeterminadas. Su línea de mitigación recomienda 2.3.1 para Java 6, 2.12.3 para Java 7, o 2.16.0 para Java 8 o superior.
Pon las fuentes una al lado de la otra:
| Pregunta | Registro CVE (cve.org) | NVD | Aviso del proveedor |
|---|---|---|---|
| ¿Qué componente? | Apache Log4j2, log4j-core | 396 entradas de coincidencia CPE en total | Solo log4j-core; log4j-api por sí solo no está afectado |
| ¿Qué versión está corregida? | No afectado desde 2.15.0 | Refleja los rangos afectados como coincidencias CPE | 2.15.0 para Java 8 o superior, luego considerada incompleta; se recomienda 2.16.0 |
| ¿Qué tan severa? | Métrica del CNA "critical", sin puntaje | CVSS v3.1 10.0 CRITICAL, v2 9.3 | Sin puntaje en el texto que leímos |
| ¿Explotada? | Ningún campo de explotación en el JSON del CNA que leímos | Entrada KEV agregada el 2021-12-10 | No consta en el texto que leímos |
Quien se detuviera en la línea "no afectado desde 2.15.0" del registro elegiría la 2.15.0 como destino. El aviso dice que la corrección de la 2.15.0 quedó incompleta y apunta a la 2.16.0 para Java 8 o superior. El registro mostró las afirmaciones de versión del CNA en el momento en que se escribieron. El aviso muestra lo que el proveedor indica instalar ahora.
Leer el puntaje CVSS como tu riesgo. El puntaje supone acceso e impacto. Tu exposición depende de si el componente es alcanzable y de si la configuración está activada. Usa el puntaje para ordenar el trabajo y luego verifica el alcance.
Quedarse en el rango de versiones del registro. El aviso es la fuente de la versión que debes instalar. Compruébalo siempre.
Tomar "no aparece en la lista" como "no afectado". Un producto que no figura en la lista puede seguir afectado. La lista depende del trabajo del CNA y del análisis de la NVD, y ambos llevan tiempo.
Esperar un CVE para cada problema. Muchas correcciones de proveedores salen sin ID. La ausencia de CVE no es prueba de seguridad.
Confundir las fechas. Reserva, publicación, última actualización y última modificación son eventos distintos de fuentes distintas. Indica la fuente junto a cada fecha que cites.
Probar un CVE en sistemas que no son tuyos. El laboratorio es de solo lectura. Reproducir una falla en un objetivo que no controlas necesita permiso por escrito de su dueño. Usa un laboratorio que hayas montado, con la versión de software que estás estudiando.
Lee el aviso del proveedor de cada producto que usas y suscríbete a su feed de seguridad. En sistemas de producción, la página del proveedor es el registro que tu control de cambios debe citar.
Agrupa los tipos de CWE de los CVE que sigues, y revisa el catálogo KEV de CISA cuando llegue una lista larga de CVE nuevos en una semana. KEV es una lista corta de fallas con explotación confirmada, lo que la convierte en un filtro útil.
Siguiente en esta serie, Qué es CVSS explica cómo se construye el 10.0 de este registro y por qué el puntaje base es solo uno de los datos de una decisión de prioridad.
Inteligencia de vulnerabilidades
Qué significa una puntuación CVSS como 9.8, cómo se construyen las vector strings de v4.0 y v3.1 y cómo decodificar y recalcular una a mano.
Inteligencia de vulnerabilidades
Ordena CVE con el catálogo KEV de CISA y las puntuaciones EPSS de FIRST, junto a CVSS, y arma una tabla de prioridades.