Vulnerability prioritization is a crucial phase where the relative risks and remediation order of vulnerabilities are evaluated, ranked from highest to lowest priority. In my previous article, I discussed how to manage security vulnerabilities using Budibase. In this article, I'll guide you through my custom approach to assessing remediation priority and demonstrate how I integrated this functionality into the Budibase platform. how to manage security vulnerabilities using Budibase Several challenges often arise during the remediation process: There is a high volume of vulnerabilities with varying risk levels across different assets. Relying solely on CVSS risk scores to determine priority is not always effective, as penetration testing frequently reveals. Some vulnerabilities cannot be remediated quickly due to poorly designed application development processes or, in some cases, a lack of vendor support. There is a high volume of vulnerabilities with varying risk levels across different assets. Relying solely on CVSS risk scores to determine priority is not always effective, as penetration testing frequently reveals. Some vulnerabilities cannot be remediated quickly due to poorly designed application development processes or, in some cases, a lack of vendor support. Theory and Priority Metrics After scanning for vulnerabilities, it's essential to analyze the results and set remediation priorities. Regularly applying patches can resolve most vulnerabilities with minimal effort. However, there are instances where it's necessary to closely examine specific vulnerabilities and assess the associated risks. If immediate remediation isn't feasible, consider implementing compensating controls. For example, if you identify an SQL injection vulnerability in a web application that cannot be patched quickly, you might use a Web Application Firewall (WAF) as a compensating control, with a relevant signature for that vulnerability. For evaluation purposes, I have created an interface in Budibase that allows me to quantitatively assess priority vulnerabilities and export a list in .csv format for our colleagues. I will outline the main metrics on which I built my filters: Time Since Vulnerability Disclosure: The longer a vulnerability remains unpatched, the greater the likelihood that an exploit will emerge in the future. However, as time passes, more compensating controls and patches typically become available. Conversely, if a vulnerability was disclosed recently, it’s unrealistic to expect immediate patching from your team. Therefore, I’ve added a filter to exclude vulnerabilities that are younger than X days. Asset Criticality: This metric assesses the importance of an asset if it would be compromised. Asset Location: This factor helps determine how exposed the asset is from uncontrolled network segments and what compensating controls apply based on its placement. I combined this metric with criticality; assets located on the perimeter are flagged as high priority. Vulnerability Trendiness: This indicates whether the vulnerability is currently being exploited. If a vendor or threat intelligence provider offers a trending score, this parameter can be utilized in the filter. Exploit Vector: This is derived from CVSS metrics, such as local versus remote exploitability. Exploit Availability: This indicates whether a working exploit already exists for the vulnerability. CVSS Severity: This reflects the base criticality rating according to standard CVSS metrics. Patch Availability: This indicates whether vendor fixes or updates exist to remediate the vulnerability. Time Since Vulnerability Disclosure: The longer a vulnerability remains unpatched, the greater the likelihood that an exploit will emerge in the future. However, as time passes, more compensating controls and patches typically become available. Conversely, if a vulnerability was disclosed recently, it’s unrealistic to expect immediate patching from your team. Therefore, I’ve added a filter to exclude vulnerabilities that are younger than X days. Time Since Vulnerability Disclosure Asset Criticality: This metric assesses the importance of an asset if it would be compromised. Asset Criticality Asset Location: This factor helps determine how exposed the asset is from uncontrolled network segments and what compensating controls apply based on its placement. I combined this metric with criticality; assets located on the perimeter are flagged as high priority. Asset Location Vulnerability Trendiness: This indicates whether the vulnerability is currently being exploited. If a vendor or threat intelligence provider offers a trending score, this parameter can be utilized in the filter. Vulnerability Trendiness Exploit Vector: This is derived from CVSS metrics, such as local versus remote exploitability. Exploit Vector Exploit Availability: This indicates whether a working exploit already exists for the vulnerability. Exploit Availability CVSS Severity: This reflects the base criticality rating according to standard CVSS metrics. CVSS Severity Patch Availability: This indicates whether vendor fixes or updates exist to remediate the vulnerability. Patch Availability These metrics collectively help prioritize vulnerabilities based on their potential impact and the efficiency of response strategies. Implementing Prioritization Filters in Budibase The main goal of this implementation is to ensure that whenever any filter parameters are changed, the dashboards and related data are automatically updated. This allows colleagues responsible for patching to export the most relevant results. In Budibase, filtering is done through UI filter elements. The value that is selected is passed as a variable to the SQL query using bindings. These variables are configured in the settings of the chart element. The bindings are displayed in the center of the image below, as shown in the example. In the SQL query, variables are inserted using double curly brackets {{ var }} at the appropriate locations. This ensures a fully functional SQL query. The SQL query is created in the Data tab under the database connection section. That’s also where you define the bindings for the SQL query and set default values in case the filter is empty or nothing is selected. Examples of SQL Queries with Prioritization for Dashboard Creation Here are several examples of SQL queries that can be used to create dashboards, each featuring prioritization filters. Dashboard 1: Top 10 Most Vulnerable Assets Dashboard 1: Top 10 Most Vulnerable Assets SELECT COUNT(hostname) AS total, hostname FROM mat_allassets WHERE osname ILIKE '%windows 20%' AND status = 'new' AND VulnerabilityIssueTime < CURRENT_DATE - {{days}}::interval AND ( CASE WHEN {{ sev }}::text IS NULL THEN TRUE ELSE severity = {{ sev }}::text END ) AND ( CASE WHEN {{expltbl}}::bool IS NULL THEN TRUE ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text END ) AND ( CASE WHEN {{netvector}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasNetworkAttackVector: {{netvector}}%'::text END ) AND ( CASE WHEN {{remedy}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasFix: {{remedy}}%'::text END ) AND ( CASE WHEN {{vulntrend}}::bool IS NULL THEN TRUE ELSE VulnerIsTrend = '{{vulntrend}}'::text END ) AND ( CASE WHEN {{hostimport}}::text IS NULL THEN TRUE ELSE HostImportance = '{{hostimport}}'::text END ) GROUP BY hostname ORDER BY total DESC LIMIT 10; SELECT COUNT(hostname) AS total, hostname FROM mat_allassets WHERE osname ILIKE '%windows 20%' AND status = 'new' AND VulnerabilityIssueTime < CURRENT_DATE - {{days}}::interval AND ( CASE WHEN {{ sev }}::text IS NULL THEN TRUE ELSE severity = {{ sev }}::text END ) AND ( CASE WHEN {{expltbl}}::bool IS NULL THEN TRUE ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text END ) AND ( CASE WHEN {{netvector}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasNetworkAttackVector: {{netvector}}%'::text END ) AND ( CASE WHEN {{remedy}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasFix: {{remedy}}%'::text END ) AND ( CASE WHEN {{vulntrend}}::bool IS NULL THEN TRUE ELSE VulnerIsTrend = '{{vulntrend}}'::text END ) AND ( CASE WHEN {{hostimport}}::text IS NULL THEN TRUE ELSE HostImportance = '{{hostimport}}'::text END ) GROUP BY hostname ORDER BY total DESC LIMIT 10; Dashboard 2: Top 10 Vulnerable Services Dashboard 2: Top 10 Vulnerable Services SELECT COUNT(hostname) AS total, VulnerableEntity || ' ' || VulnerableEntityVersion AS VulnerableObject FROM mat_allassets WHERE osname ILIKE '%windows 20%' AND VulnerableEntity IS NOT NULL AND status = 'new' AND VulnerabilityIssueTime < CURRENT_DATE - {{days}}::interval AND ( CASE WHEN {{ sev }}::text IS NULL THEN TRUE ELSE severity = {{ sev }}::text END ) AND ( CASE WHEN {{expltbl}}::bool IS NULL THEN TRUE ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text END ) AND ( CASE WHEN {{expltbl}}::bool IS NULL THEN TRUE ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text END ) AND ( CASE WHEN {{netvector}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasNetworkAttackVector: {{netvector}}%'::text END ) AND ( CASE WHEN {{remedy}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasFix: {{remedy}}%'::text END ) AND ( CASE WHEN {{vulntrend}}::bool IS NULL THEN TRUE ELSE VulnerIsTrend = '{{vulntrend}}'::text END ) AND ( CASE WHEN {{hostimport}}::text IS NULL THEN TRUE ELSE HostImportance = '{{hostimport}}'::text END ) GROUP BY VulnerableObject ORDER BY total DESC LIMIT 10; SELECT COUNT(hostname) AS total, VulnerableEntity || ' ' || VulnerableEntityVersion AS VulnerableObject FROM mat_allassets WHERE osname ILIKE '%windows 20%' AND VulnerableEntity IS NOT NULL AND status = 'new' AND VulnerabilityIssueTime < CURRENT_DATE - {{days}}::interval AND ( CASE WHEN {{ sev }}::text IS NULL THEN TRUE ELSE severity = {{ sev }}::text END ) AND ( CASE WHEN {{expltbl}}::bool IS NULL THEN TRUE ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text END ) AND ( CASE WHEN {{expltbl}}::bool IS NULL THEN TRUE ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text END ) AND ( CASE WHEN {{netvector}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasNetworkAttackVector: {{netvector}}%'::text END ) AND ( CASE WHEN {{remedy}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasFix: {{remedy}}%'::text END ) AND ( CASE WHEN {{vulntrend}}::bool IS NULL THEN TRUE ELSE VulnerIsTrend = '{{vulntrend}}'::text END ) AND ( CASE WHEN {{hostimport}}::text IS NULL THEN TRUE ELSE HostImportance = '{{hostimport}}'::text END ) GROUP BY VulnerableObject ORDER BY total DESC LIMIT 10; Dashboard 3: Top 10 Active CVEs Dashboard 3: Top 10 Active CVEs SELECT COUNT(DISTINCT hostname) AS total, cve FROM mat_allassets WHERE osname ILIKE '%windows 20%' AND status = 'new' AND cve IS NOT NULL AND VulnerabilityIssueTime < CURRENT_DATE - {{ days }}::interval AND ( CASE WHEN {{ sev }}::text IS NULL THEN TRUE ELSE severity = {{ sev }}::text END ) AND ( CASE WHEN {{expltbl}}::bool IS NULL THEN TRUE ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text END ) AND ( CASE WHEN {{netvector}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasNetworkAttackVector: {{netvector}}%'::text END ) AND ( CASE WHEN {{remedy}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasFix: {{remedy}}%'::text END ) AND ( CASE WHEN {{vulntrend}}::bool IS NULL THEN TRUE ELSE VulnerIsTrend = '{{vulntrend}}'::text END ) AND ( CASE WHEN {{hostimport}}::text IS NULL THEN TRUE ELSE HostImportance = '{{hostimport}}'::text END ) GROUP BY cve ORDER BY total DESC LIMIT 10; SELECT COUNT(DISTINCT hostname) AS total, cve FROM mat_allassets WHERE osname ILIKE '%windows 20%' AND status = 'new' AND cve IS NOT NULL AND VulnerabilityIssueTime < CURRENT_DATE - {{ days }}::interval AND ( CASE WHEN {{ sev }}::text IS NULL THEN TRUE ELSE severity = {{ sev }}::text END ) AND ( CASE WHEN {{expltbl}}::bool IS NULL THEN TRUE ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text END ) AND ( CASE WHEN {{netvector}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasNetworkAttackVector: {{netvector}}%'::text END ) AND ( CASE WHEN {{remedy}}::bool IS NULL THEN TRUE ELSE metrics ILIKE '%HasFix: {{remedy}}%'::text END ) AND ( CASE WHEN {{vulntrend}}::bool IS NULL THEN TRUE ELSE VulnerIsTrend = '{{vulntrend}}'::text END ) AND ( CASE WHEN {{hostimport}}::text IS NULL THEN TRUE ELSE HostImportance = '{{hostimport}}'::text END ) GROUP BY cve ORDER BY total DESC LIMIT 10; What It All Yields In the end, this setup became a straightforward yet effective tool for highlighting the most problematic assets and services based on the most critical vulnerabilities. It also allows for easy export of this information as needed. Takeaway: Not having a budget for an expensive vulnerability management (VM) platform doesn’t mean you can’t effectively prioritize vulnerabilities. Many commercial VM solutions may lack the level of prioritization flexibility that specific infrastructures require. Takeaway: In the next article, I will explore the Exploit Prediction Scoring System (EPSS), demonstrate how to implement it in Budibase, and add functionality for exporting a list of prioritized vulnerabilities. Exploit Prediction Scoring System (EPSS) I would love to hear from you: Do you use vulnerability prioritization in your work? How do you track critical assets? Do you use vulnerability prioritization in your work? Do you use vulnerability prioritization in your work? How do you track critical assets? How do you track critical assets?