API Rug Pull - The NIST NVD Database and API (Part 4 of 3)
A while back I got an email from Perry, one of our readers who was having a problem using my cvescan script, which I covered in a 3 part story back in 2021:
- https://isc.sans.edu/forums/diary/Using+the+NIST+Database+and+API+to+Keep+Up+with+Vulnerabilities+and+Patches+Part+1+of+3/26958/
- https://isc.sans.edu/forums/diary/Using+the+NIST+Database+and+API+to+Keep+Up+with+Vulnerabilities+and+Patches+Playing+with+Code+Part+2+of+3/26964/
- https://isc.sans.edu/forums/diary/Using+the+NVD+Database+and+API+to+Keep+Up+with+Vulnerabilities+and+Patches+Tool+Drop+CVEScan+Part+3+of+3/26974/
The problem was simple, the script had just stopped working. The NVD API version 1.0 had been retired in Dec 2023, and of course I had no idea. A quick visit to their website got me the details of this change:
- https://nvd.nist.gov/general/news/nvd-program-transition-announcement
- https://nvd.nist.gov/general/news/api-20-announcements
Anyway - this turned into a simple enough set of changes for my script, but some fundamental changes to the API itself. Full docs for the API start here:
First, they moved from an open restful API to one that (they say) requires an API key (more on this later). This takes care of change notifications in future, because you have to register to get a key. Watch your spam folder, Outlook helpfully placed the email with the registration link in it in my Junk Email folder.
The original call in the NVD 1.0 API to collect CVE's for a specific product IOD (CPE) is:
$request = "https://services.nvd.nist.gov/rest/json/cves/1.0?modStartDate=" + $StartDate + "&cpeMatchString=" + $app.cpe $CVEs = (invoke-webrequest $request | ConvertFrom-Json).result.CVE_items.cve.CVE_data_meta.id |
Similarly, the NVD 1.0 API call to collect the metadtaa for a specific CVE:
$request = "https://services.nvd.nist.gov/rest/json/cve/1.0/" + $CVE.CVE $cvemetadata = (invoke-webrequest $request) | convertfrom-json |
In the version 2 API, let's construct an example call, looking for CVE's in Windows 10. For a review of CPE's, check out the first 3 parts of this story. I often "feed" CVEScan by collecting CPE's using nmap for instance. Anyway, back to constructing the request:
$cpematchstring = "cpe:2.3:o:microsoft:windows_10:1607:*:*:*:*:*:*:*" $request = "https://services.nvd.nist.gov/rest/json/cves/2.0?cpeName=" + $cpematchstring |
Now let's make the call and look at the fields we get back:
(invoke-webrequest $request | ConvertFrom-Json) | gm TypeName: System.Management.Automation.PSCustomObject Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() format NoteProperty string format=NVD_CVE resultsPerPage NoteProperty int resultsPerPage=2000 startIndex NoteProperty int startIndex=0 timestamp NoteProperty string timestamp=2024-04-23T17:40:15.370 totalResults NoteProperty int totalResults=2574 version NoteProperty string version=2.0 vulnerabilities NoteProperty Object[] vulnerabilities=System.Object[] |
Now let's look at the vulnerability list, picking just a random item in the list:
$v = (invoke-webrequest $request | ConvertFrom-Json).vulnerabilities $v[7].cve id : CVE-2016-0170 sourceIdentifier : secure@microsoft.com published : 2016-05-11T01:59:10.027 lastModified : 2018-10-12T22:11:24.817 vulnStatus : Modified descriptions : {@{lang=en; value=GDI in Microsoft Windows Vista SP2, Windows Server 2008 SP2 and R2 SP1, Windows 7 SP1, Windows 8.1, Windows Server 2012 Gold and R2, Windows RT 8.1, and Windows 10 Gold and 1511 allows remote attackers to execute arbitrary code via a crafted document, aka "Windows Graphics Component RCE Vulnerability."}, @{lang=es; value=GDI en Microsoft Windows Vista SP2, Windows Server 2008 SP2 y R2 SP1, Windows 7 SP1, Windows 8.1, Windows Server 2012 Gold y R2, Windows RT 8.1 y Windows 10 Gold y 1511 permite a atacantes remotos ejecutar c??digo arbitrario a trav??s de un documento manipulado, tambi??n conocido como "Windows Graphics Component RCE Vulnerability".}} metrics : @{cvssMetricV30=System.Object[]; cvssMetricV2=System.Object[]} weaknesses : {@{source=nvd@nist.gov; type=Primary; description=System.Object[]}} configurations : {@{nodes=System.Object[]}} references : {@{url=http://packetstormsecurity.com/files/137096/Microsoft-Windows-gdi32.dll-ExtEscape-Buffer-Over flow.html; source=secure@microsoft.com}, @{url=http://www.securityfocus.com/bid/89864; source=secure@microsoft.com}, @{url=http://www.securitytracker.com/id/1035823; source=secure@microsoft.com}, @{url=https://docs.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-055; source=secure@microsoft.com}} |
There's no need for a second call, all the NVD metadata is in the returned data for that first call! You can just keep parsing as deep as you want until you get the exact fields that you want! For instance, if we just want the CVE list:
$cvelist = $v.id $cvelist CVE-2013-3900 CVE-2015-6184 CVE-2016-0088 ... and so on |
Or if you wanted the CVE list and the last modified date:
$datelist = (invoke-webrequest $request | ConvertFrom-Json).vulnerabilities.cve | select id,lastModified $datelist id lastModified -- ------------ CVE-2013-3900 2022-11-02T15:15:43.850 CVE-2015-6184 2018-10-12T22:10:41.470 CVE-2016-0088 2018-10-12T22:11:00.707 CVE-2016-0089 2018-10-12T22:11:00.910 .. and so on |
Sticking with our favourite item lucky 7, the description would be:
$v[7].cve.descriptions[0].value GDI in Microsoft Windows Vista SP2, Windows Server 2008 SP2 and R2 SP1, Windows 7 SP1, Windows 8.1, Windows Server 2012 Gold and R2, Windows RT 8.1, and Windows 10 Gold and 1511 allows remote attackers to execute arbitrary code via a crafted document, aka "Windows Graphics Component RCE Vulnerability." |
To get exploitability and import scores for both version 2 and version 3 of the CVSS Metric:
$v[7].cve.metrics.cvssmetricv2 ource : nvd@nist.gov type : Primary cvssData : @{version=2.0; vectorString=AV:N/AC:M/Au:N/C:C/I:C/A:C; accessVector=NETWORK; accessComplexity=MEDIUM; authentication=NONE; confidentialityImpact=COMPLETE; integrityImpact=COMPLETE; availabilityImpact=COMPLETE; baseScore=9.3} baseSeverity : HIGH exploitabilityScore : 8.6 impactScore : 10.0 acInsufInfo : False obtainAllPrivilege : False obtainUserPrivilege : False obtainOtherPrivilege : False userInteractionRequired : True
$v[7].cve.metrics.cvssmetricv2.impactscore 10.0 $v[7].cve.metrics.cvssmetricv2.exploitabilityscore 8.6 |
And for v3:
$v[7].cve.metrics.cvssmetricv30 source : nvd@nist.gov type : Primary cvssData : @{version=3.0; vectorString=CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H; attackVector=NETWORK; attackComplexity=LOW; privilegesRequired=NONE; userInteraction=REQUIRED; scope=UNCHANGED; confidentialityImpact=HIGH; integrityImpact=HIGH; availabilityImpact=HIGH; baseScore=8.8; baseSeverity=HIGH} exploitabilityScore : 2.8 impactScore : 5.9
$v[7].cve.metrics.cvssmetricv30.exploitabilityscore 2.8 $v[7].cve.metrics.cvssmetricv30.impactscore 5.9
$v[7].cve.metrics.cvssmetricv30.cvssdata version : 3.0 vectorString : CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H attackVector : NETWORK attackComplexity : LOW privilegesRequired : NONE userInteraction : REQUIRED scope : UNCHANGED confidentialityImpact : HIGH integrityImpact : HIGH availabilityImpact : HIGH baseScore : 8.8 baseSeverity : HIGH
$v[7].cve.metrics.cvssmetricv30.cvssdata.basescore 8.8 |
Going back to collect the URL references:
$v[7].cve.references | fl
url : http://packetstormsecurity.com/files/137096/Microsoft-Windows-gdi32.dll-ExtEscape-Buffer-Overflow.html source : secure@microsoft.com url : http://www.securityfocus.com/bid/89864 source : secure@microsoft.com url : http://www.securitytracker.com/id/1035823 source : secure@microsoft.com url : https://docs.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-055 source : secure@microsoft.com So, for just the URLs: $v[7].cve.references.url http://packetstormsecurity.com/files/137096/Microsoft-Windows-gdi32.dll-ExtEscape-Buffer-Overflow.html http://www.securityfocus.com/bid/89864 http://www.securitytracker.com/id/1035823 https://docs.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-055 |
The API key? So far I haven't needed it. This may just be a way of the NVD folks getting a list of the developers that use their API (with email addresses), so that they can tell us in advance when API 2.1 or 3.0 is about to be released(?) If it is, I'm 100% OK with that, I WANT to know in advance if someone else is going to break my code!
As always, I'll update my cvescan script in the next few days to match the new API, you can find it in my github then at https://github.com/robvandenbrink
If you have used external APIs in your code, then had the API unexpectedly change on you and bite you, please use our comment form and share the details (if your NDA permits?)
===============
Rob VandenBrink
rob@coherentsecurity.com
Comments