Understanding CVSS Metrics
01. Background
The first thing we look at when a vulnerability report comes in is the CVSS score. That score determines the order of response, and most scanner reports and asset management dashboards sort everything by this single number.
But right next to that score, there's always a string like this:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N
This string is one of the components that make up the score. I used to just skip past it, but while working on some related research recently I came to understand what it means, found it useful, and decided to make it the topic of this post.
This post covers CVSS version 3.1. The latest version is 4.0, but since 3.1 is what I deal with most, I went with 3.1. You can find the 4.0 specification at the link below.
https://www.first.org/cvss/v4.0/
02. Why?
What's the benefit of understanding CVSS Metrics?
A CVSS Score is a single number calculated by taking into account things like the vulnerability's type and impact. Because it compresses multiple pieces of information into one value, there are things hidden behind it.
1. The same score doesn't mean the same vulnerability
Both vulnerabilities below fall under High severity, and their scores differ by only 0.5.
CVE-2014-0160 Heartbleed 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CVE-2016-5195 Dirty COW 7.0 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
Yet their characteristics are completely different. One reads memory from the internet without authentication, while the other is a local privilege escalation that you can only use once you're already on the server.
If Heartbleed exists on an externally exposed asset, it needs to be handled immediately. But Dirty COW on an internal server with controlled access may allow relatively more time. Since it's common for score order and actual response order to diverge, the score alone isn't enough to make a judgment.
2. You can get the outline without reading the full CVE description
Properly understanding a single CVE means checking the description, the vendor advisory, and the patch notes. When dozens of them pile up in a list, going through all of them isn't realistic.
But if you go by the vector, you can quickly grasp roughly how the vulnerability is triggered and what impact it has. It's useful as a criterion for separating what to examine now from what to look at later.
3. You can automate it
This is the decisive reason I started looking into CVSS Metrics.
Vectors are standardized strings, which makes them easy to handle programmatically. The NVD API provides a parameter for querying by vector conditions directly, and adding CWE or Impact conditions on top of that lets you pull a precisely targeted list.
In my case, the nature of my work means I mainly hunt for RCE and LPE vulnerabilities, and vector values let me filter down to just the ones that match those conditions.
The same applies from a CTI perspective. You can use it to monitor recent CVEs and pull out only the high-impact ones for reporting.
03. CVSS Metrics?
CVSS Metrics are a standardized set of indicators used to quantitatively assess the severity of security vulnerabilities in software and hardware.
In CVSS v3.1, the metrics are divided into three broad groups.
- Base Metric Group: characteristics intrinsic to the vulnerability that don't change over time or across environments
- Temporal Metric Group: characteristics that change over time, such as whether exploit code has been published or whether a patch exists
- Environmental Metric Group: characteristics specific to a particular organization or environment, such as the importance of the target asset
The value calculated by combining these three groups is the CVSS Score, and the representation of each individual metric's setting as a standardized string is the Vector String.
For reference, the CVSS score shown on NVD or in vendor advisories usually reflects only the Base Metrics. The specification treats Temporal and Environmental as optional and recommends that consumers fill them in themselves, but in practice that doesn't seem to happen very often.
This post won't cover the calculation method — it focuses on the Vector String.
04. Structure of the Vector String
The three groups mentioned above map directly onto the structure of the vector string.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
└─┬─┘└─────────┬─────────┘
Version Base
// Temporal and Environmental are optional, so they're usually omitted.
The vector above belongs to a well-known vulnerability: CVE-2021-44228, Log4Shell. Its Base Score is 10.0 (Critical), the maximum value that can be produced.
In v3.1, Base is divided into three parts.
AV:N/AC:L/PR:N/UI:N / S:C / C:H/I:H/A:H
└───┬─────┘ └┬┘ └──┬───┘
Exploitability Scope Impact
- Exploitability (AV, AC, PR, UI) — the conditions required for the attack to be possible
- Scope (S) — whether the damage extends beyond the original component
- Impact (C, I, A) — the outcome when the attack succeeds
Put simply, the first part (Exploitability) answers "what do I need in order to use this vulnerability," the last part (Impact) answers "what do I get if it succeeds," and Scope indicates how far that outcome spreads.
Below, I'll walk through each field and interpret this vector value piece by piece.
Exploitability
AV (Attack Vector)
The field indicating the path by which an attacker reaches the vulnerability.
| Value |
Meaning |
N Network |
Attack possible remotely, e.g. over the internet, just by sending packets (ex - RCE vulnerabilities) |
A Adjacent |
Requires access to the same physical network (Wi-Fi, Bluetooth) |
L Local |
Requires a local shell or SSH access (ex - LPE vulnerabilities) |
P Physical |
Requires physical manipulation (USB, etc.) |
In the case of Log4Shell, the vulnerability can be triggered just by sending a payload remotely via an HTTP request or similar, so it takes the Network value. On the other hand, LPE vulnerabilities like Dirty COW can be triggered from a local shell on the target, so they take the Local value.
Since remotely exploitable vulnerabilities have a larger pool of potential attackers than local ones, a vulnerability with AV set to N receives a higher CVSS score.
AC (Attack Complexity)
The field indicating whether variables outside the attacker's control (luck, environment) are required for the attack to succeed.
| Value |
Meaning |
L Low |
No special conditions required. Reproducible at any time |
H High |
Success depends on conditions outside the attacker's control |
Conditions outside the attacker's control here refer to cases with a chance of failure, such as heap spray or race conditions. Typically, this covers vulnerabilities where the attack doesn't succeed on the first try and requires multiple attempts.
In the case of Log4Shell, it triggers immediately as long as the payload is delivered, so it takes the Low value.
PR (Privileges Required)
The field indicating the level of privilege the attacker must already hold before executing the attack.
| Value |
Meaning |
N None |
No authentication or privileges required at all |
L Low |
Requires low-level privileges, such as a regular user account |
H High |
Requires high-level privileges, such as an administrator account |
Unauthenticated vulnerabilities are exactly those with a Privileges Required value of N.
Authenticated vulnerabilities are classified as L or H depending on the privileges needed. For example, if a WordPress RCE vulnerability requires a regular user account to trigger, it takes the L value. If it requires an administrator account, it's H.
In the case of Log4Shell, it triggers as long as the input is written to the log regardless of authentication, so it takes the None value.
UI (User Interaction)
The field indicating whether a victim (user) must be involved during the attack.
| Value |
Meaning |
N None |
No victim involvement required |
R Required |
Requires an active action by the victim, such as clicking a link or opening a file |
XSS is a good way to understand what victim involvement means. With XSS, sending the payload doesn't immediately set anything off — the victim has to read the link or the content containing the payload for it to work. So vulnerabilities like XSS take the R value.
Log4Shell triggers immediately without any user involvement, so it takes the None value.
At this point you can see that Log4Shell holds the highest value across all four Exploitability fields.
AV:N/AC:L/PR:N/UI:N
Scope (S)
The field indicating whether the vulnerability's impact extends beyond the originally vulnerable component into another management domain.
| Value |
Meaning |
U Unchanged |
The impact ends within the vulnerable component |
C Changed |
The impact reaches another management domain |
Honestly, this is a field I still don't fully understand. The specification explains it in terms of a concept called security authority, but compared to the other fields it's abstract, and I haven't developed a clear sense of how to judge the value.
Roughly, I understand it as taking the C value when the vulnerable target and the target that actually suffers the damage are different. For what it's worth, perhaps because of this ambiguity, the Scope field was removed in v4.0 and replaced with a notation that separates out the affected targets.
In the case of Log4Shell, the vulnerable component is a logging library, but the result is code execution across the entire host, so I interpreted it as taking the Changed value.
Impact (C / I / A)
The fields indicating what damage occurs when the attack succeeds. Each of the three pillars of information security — confidentiality, integrity, and availability — gets its own value.
| Field |
Meaning |
C Confidentiality |
How much information the attacker shouldn't see becomes visible to them |
I Integrity |
How much the attacker can tamper with data or the system |
A Availability |
How much the availability of the target service is degraded |
All three fields take one of the three values below.
| Value |
Meaning |
H High |
Total loss. Or a partial loss that is nonetheless decisive |
L Low |
There is some loss, but the attacker can't control its scope or content |
N None |
No impact in that area |
Reading the three values as a combination reveals roughly what type of vulnerability it is.
| Combination |
Type |
C:H/I:H/A:H |
Full compromise (ex - RCE) |
C:H/I:N/A:N |
Information disclosure (ex - Heartbleed, LFI) |
C:N/I:H/A:N |
Tampering |
C:N/I:N/A:H |
Denial of service (ex - DoS) |
In the case of Log4Shell, remote code execution is possible, so all three fields take the High value.
Temporal / Environmental
Besides the Base group covered so far, there are two more groups. They rarely show up in vector strings, but let's take a quick look at what they contain.
Temporal covers values that change over time.
| Field |
Meaning |
E Exploit Code Maturity |
How mature the exploit is (PoC level, or running reliably) |
RL Remediation Level |
Whether a patch or workaround has been released |
RC Report Confidence |
How certain the report is |
All three fields are coefficients of 1.0 or less, so Temporal only works in the direction of lowering the Base score. The idea is that if an official patch has been released, the risk has come down accordingly.
Environmental is the group for re-scoring values against your own environment. CR/IR/AR reflect how important confidentiality, integrity, and availability each are for the asset in question, and fields like MAV/MAC/MPR let you override the Base values.
05. Conclusion
If you can read CVSS Metrics, you can judge the rough character of a given CVE. How it's reached, what preconditions it requires, and what gets damaged on success are all contained in those eight fields.
Looking again at the Log4Shell vector we examined earlier, it reads like this:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H 10.0 CRITICAL
It's reachable remotely (AV:N), reproduces without any special conditions (AC:L), and requires neither prior privileges (PR:N) nor user involvement (UI:N). On top of that, the damage crosses beyond the original component (S:C), and confidentiality, integrity, and availability are all completely lost (C:H/I:H/A:H). There are no preconditions whatsoever, and the damage is total.
What I find most useful is filtering. You can use each of the metric fields to strain out the noise, gather only the type of vulnerability you want, and feed that into other work.
The NVD API does in fact provide a parameter for querying by vector conditions directly.
// Only vulnerabilities triggerable remotely with no preconditions
https://services.nvd.nist.gov/rest/json/cves/2.0?cvssV3Metrics=AV:N/AC:L/PR:N/UI:N
I suspect the CTI services on Telegram and various forums that surface only the serious vulnerabilities work along similar lines. Set the conditions to match your purpose, and you can monitor recent CVEs while pulling out only what you need.
References