# Flashpoint (VulnDB)

## Prioritize Vulnerability with Threat Intelligence from VulnDB

{% embed url="<https://youtu.be/onvSZShtEB4?si=yNulV32SL5qczdR>\_" %}

The purpose of this example is to prioritize a vulnerability based on threat intelligence information harnessed from [FlashPoint VulnDB](https://flashpoint.io/ignite/vulnerability-intelligence/) and to apply a custom score/rating to the vulnerability.

This example Flow can be downloaded from our [Flows GitHub Repository](https://github.com/AttackForge/Flows) and [imported](#importing-exporting-flows) into your AttackForge.

**Initial Set Up**

> **Important**: This example requires access to the AttackForge Self-Service API and AttackForge Flows

* **Event**: Vulnerability Created
* **Secrets**:
  * af\_auth - your [AttackForge Self-Service API token](https://support.attackforge.com/attackforge-enterprise/modules/self-service-restful-api/getting-started#accessing-the-restful-api).
  * vulndb\_client\_id - your VulnDB Client Id
  * vulndb\_client\_secret - your VulnDB Client Secret

**Action 1 - Get VulnDB OAuth Token**&#x20;

* **Method**: POST
* **URL**: <https://vulndb.flashpoint.io/oauth/token>
* **Headers**:
  * Key = Content-Type; Type = Value; Value = application/json
* **Request Script**:

```javascript
let cve;

if (data.vulnerability_custom_fields) {
    for (let i = 0; i < data.vulnerability_custom_fields.length; i++) {
      if (data.vulnerability_custom_fields[i].key === 'cve') {
        cve = data.vulnerability_custom_fields[i].value;
        break;
      }
    }
}

if (!cve) {
  return {
    decision: { 
      status: 'finish',
      message: 'No CVE found'
    }
  };
}

return {
  data: {
    cve: cve,
    vuln: data
  },
  request: {
    body: {
      client_id: secrets.vulndb_client_id,
      client_secret: secrets.vulndb_client_secret,
      grant_type: 'client_credentials'
    }
  }
};
```

* **Response Script**:

```javascript
let body;

if (response.headers['Content-Type'] === 'application/json; charset=utf-8') {
  body = JSON.parse(response.body);
}
else {
  return {
    decision: {
      status: 'abort',
      message: 'Content-Type is expected to be application/json; charset=utf-8'
    }
  };
}

if (body?.access_token) {
  return {
    data: {
      vulnDBToken: body.access_token,
      cve: data?.cve,
      vuln: data?.vuln
    } 
  };
}
else {
  return {
    decision: { 
      status: 'abort',
      cause: 'VulnDB access token not found'
    }
  };
}
```

**Action 2 - Get Threat Intel for Vuln from VulnDB**

* **Method**: \<defined in Request Script>
* **URL**: \<defined in Request Script>
* **Headers**:
  * Key = Content-Type; Type = Value; Value = application/json
  * \<others defined in Request Script>
* **Request Script**:

```javascript
if (data?.vulnDBToken && data?.cve && data?.vuln) {
  return {
    data: {
      cve: data.cve,
      vuln: data.vuln
    },
    request: { 
      url: 'https://vulndb.flashpoint.io/api/v2/vulnerabilities/' + data.cve + '/find_by_cve_id',
      headers: {
        Authorization: 'Bearer ' + data.vulnDBToken
      }
    }
  };
}
else {
  return {
    decision: { 
      status: 'abort',
      message: 'VulnDB access token not found'
    }
  };
}
```

* **Response Script**:

```javascript
let body;

if (response.headers['Content-Type'] === 'application/json; charset=utf-8') {
  body = JSON.parse(response.body);
}
else {
  return {
    decision: {
      status: 'abort',
      message: 'Content-Type is expected to be application/json; charset=utf-8'
    }
  };
}

if (!body?.results?[0]) {
  return {
    decision: { 
      status: 'abort',
      message: 'VulnDB CVE not found'
    }
  };
}

return {
  data: {
    cve: data?.cve,
    vulnDB: body.results[0],
    vuln: data?.vuln
  } 
};
```

**Action 3 - Apply Threat Intel, Prioritize Vulnerability and Update Vulnerability**

* **Method**: \<defined in Request Script>
* **URL**: \<defined in Request Script>
* **Headers**:
  * Key = Content-Type; Type = Value; Value = application/json
  * Key = X-SSAPI-KEY; Type = Secret; Value = af\_auth
* **Request Script**:

```javascript
if (data?.vuln && data?.vulnDB) {
  const score = calculateScore(data.vuln, data.vulnDB);
  const priority = convertScoreToPriority(score);

  return {
      request: {
        url: 'https://demo.attackforge.dev/api/ss/vulnerability/' + data.vuln.vulnerability_id,
        body: {
          priority: priority,
          custom_fields: [
            {
              key: 'threat_score',
              value: JSON.stringify(score)
            }
          ]
        }
      }
  };
}
else {
  return {
    decision: { 
      status: 'abort',
      message: 'Missing required vuln data'
    }
  };
}

function calculateScore(vuln, vdb) {
  let score = 0;

  // Maximum score = 140
  // Higher the score = Higher Priority to fix!

  // [ THREAT CONTEXT ]

  const internetFacing = isInternetFacing(vuln);

  // Is the threat related to exposed/internet-facing services?
  if (internetFacing) {
    score += 10;
  }

  if (vdb.cvss_version_three_metrics) {
    for (let i = 0; i < vdb.cvss_version_three_metrics.length; i++) {
      const metrics = vdb.cvss_version_three_metrics[i];

      // Is the CVSS score 8 or higher?
      if (metrics.score !== undefined && metrics.score >= 8) {
        score += 5;
      }

      // Is the threat easily exploitable?
      if (metrics.attack_complexity === 'HIGH') {
        score += 1;
      }
      else if (metrics.attack_complexity === 'MEDIUM') {
        score += 5;
      }
      else if (metrics.attack_complexity === 'LOW') {
        score += 10;
      }

      // No user interaction required?
      if (metrics.user_interaction === 'NONE') {
        if (isInternetFacing) {
          score += 10;
        }
        else {
          score += 5;
        }
      }
    }
  }
  else if (vdb.cvss_metrics) {
    for (let i = 0; i < vdb.cvss_metrics.length; i++) {
      const metrics = vdb.cvss_metrics[i];

      // Is the CVSS score 8 or higher?
      if (metrics.score !== undefined && metrics.score >= 8) {
        score += 5;
      }

      // Is the threat easily exploitable?
      if (metrics.attack_complexity === 'HIGH') {
        score += 1;
      }
      else if (metrics.attack_complexity === 'MEDIUM') {
        score +=  5;
      }
      else if (metrics.attack_complexity === 'LOW') {
        score += 10;
      }
    }
  }

  if (vdb.classifications) {
    for (let i = 0; i < vdb.classifications.length; i++) {
      const classifications = vdb.classifications[i];

      // Is there a public exploit available for this threat?
      if (classifications.name === 'exploit_public') {
        if (isInternetFacing) {
          score += 10;
        }
        else {
          score += 5;
        }
      }
      // Does this threat require configuration changes?
      else if (classifications.name === 'solution_workaround') {
        score += 5;
      }
      // Does the threat grant unauthorized access?
      else if (classifications.name === 'location_remote') {
        if (isInternetFacing) {
          score += 10;
        }
        else {
          score += 5;
        }
      }
      // Disclosure in the wild?
      else if (classifications.name === 'disclosure_in_wild') {
        score += 5;
      }
      else if (classifications.name === 'disclosure_uncoordinated_disclosure') {
        score += 5;
      }
      // Wormable?
      else if (classifications.name === 'exploit_wormified') {
        if (isInternetFacing) {
          score += 15;
        }
        else {
          score += 10;
        }
      }
      // Virus / Malware?
      else if (classifications.name === 'exploit_virus_malware') {
        if (isInternetFacing) {
          score += 10;
        }
        else {
          score += 5;
        }
      }
      // PoC Public?
      else if (classifications.name === 'exploit_poc_public') {
        if (isInternetFacing) {
          score += 15;
        }
        else {
          score += 10;
        }
      }
    }
  }

  // Is a patch available for this threat?
  let patchExists = false;

  if (vdb.classifications) {
    for (let i = 0; i < vdb.classifications.length; i++) {
      const classifications = vdb.classifications[i];

      if (classifications.name === 'solution' || classifications.name === 'solution_upgrade') {
        patchExists = true;
        break;
      }
    }
  }
  else if (vdb.cvss_version_three_metrics) {
    for (let i = 0; i < vdb.cvss_version_three_metrics.length; i++) {
      const metrics = vdb.cvss_version_three_metrics[i];

      if (metrics.remediation_level === 'OFFICIAL_FIX' || metrics.remediation_level === 'TEMPORARY_FIX') {
        patchExists = true;
        break;
      }
    }
  }

  if (!patchExists) {
    score += 10;
  }

  // Social Risk Score (Vuln DB)
  if (vdb.social_risk_score === 'High') {
    score += 5;
  }
  else if (vdb.social_risk_score === 'Medium') {
    score += 3;
  }
  else if (vdb.social_risk_score === 'Low') {
    score += 1;
  }

  // What is the likelihood that this threat could be used in a ransomware attack?
  if (vdb.ransomware_likelihood === 'High') {
    if (isInternetFacing) {
      score += score + 10;
    }
    else {
      score += 5;
    }
  }
  else if (vdb.ransomware_likelihood === 'Medium') {
    if (isInternetFacing) {
      score += 5;
    }
    else {
      score += 3;
    }
  }
  else if (vdb.ransomware_likelihood === 'Low') {
    score += 1;
  }

  if (vdb.tags) {
    for (let i = 0; i < vdb.tags.length; i++) {
      // Is this a known CISA KEV vulnerability?
      if (vdb.tags[i] === 'cisa_kev') {
        score += 10;
        break;
      }
    }
  }

  return score;
}

function convertScoreToPriority(score) {
  if (score > 0 && score <= 30) {
    return 'Low';
  }
  else if (score > 30 && score <= 70) {
    return 'Medium';
  }
  else if (score > 70 && score <= 110) {
    return 'High';
  }
  else if (score > 110 && score <= 140) {
    return 'Critical';
  }
  else {
    return 'Info';
  }
}

function isInternetFacing(vuln) {
  if (vuln.vulnerability_affected_assets) {
    for (let i = 0; i < vuln.vulnerability_affected_assets.length; i++) {
      if (vuln.vulnerability_affected_assets[i].asset?.custom_fields) {
        const assetCustomFields = vuln.vulnerability_affected_assets[i].asset?.custom_fields;

        for (let j = 0; j < assetCustomFields.length; j++) {
          if (assetCustomFields[j].key === 'internet_facing' && assetCustomFields[j].value === 'Yes') {
            return true;
          }
        }
      }
    }
  }

  return false;
}
```

* **Response Script**:

```javascript
let body;

if (response.headers['Content-Type'] === 'application/json') {
  body = JSON.parse(response.body);
}
else {
  return {
    decision: {
      status: 'abort',
      message: 'Content-Type is expected to be application/json'
    }
  };
}

if (response.statusCode === 200 && body?.result?.result === 'Vulnerability Updated') {
  return {
    decision: 'finish'
  };
}
else {
  Logger.error(JSON.stringify(response));

  return {
    decision: { 
      status: 'abort',
      message: 'Vulnerability not updated'
    }
  };
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://support.attackforge.com/attackforge-enterprise/modules/flows/flashpoint-vulndb.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
