- name
- Vulnerability Assessment
- description
- Systematic identification, classification, and prioritization of security vulnerabilities
- license
- MIT
- compatibility
- ["Python 3.8+","Linux"]
- audience
- Security analysts, vulnerability managers, IT administrators
- category
- Cybersecurity
# Vulnerability Assessment
## What I do
I enable systematic vulnerability identification, classification, prioritization, and tracking. I provide frameworks for scanning, risk scoring, remediation guidance, and vulnerability management program development.
## When to use me
- Setting up vulnerability scanning programs
- Analyzing and prioritizing vulnerability findings
- Creating risk-based remediation strategies
- Tracking vulnerability remediation progress
- Compliance vulnerability assessments
- Third-party/vendor security assessments
- Continuous vulnerability monitoring
- Metrics and reporting for stakeholders
## Core Concepts
- **CVE/NVD**: Common Vulnerabilities and Exposures database
- **CVSS**: Common Vulnerability Scoring System for severity
- **Asset Discovery**: Identifying all systems and software
- **Vulnerability Scanning**: Automated detection of weaknesses
- **Risk Prioritization**: Combining CVSS with asset criticality
- **Remediation Tracking**: Managing vulnerability fixes
- **Compliance Mapping**: Linking vulns to compliance frameworks
- **False Positive Analysis**: Validating scanner findings
- **Vulnerability Aging**: Tracking time to remediate
- **Metrics and KPIs**: Measuring program effectiveness
## Code Examples
### CVSS Calculator
```python
from enum import Enum
from dataclasses import dataclass
from typing import Dict, Optional
import json
class CVSSVersion(Enum):
CVSS30 = "3.0"
CVSS31 = "3.1"
CVSS40 = "4.0"
class AttackVector(Enum):
NETWORK = "N"
ADJACENT_NETWORK = "A"
LOCAL = "L"
PHYSICAL = "P"
class AttackComplexity(Enum):
LOW = "L"
HIGH = "H"
class PrivilegesRequired(Enum):
NONE = "N"
LOW = "L"
HIGH = "H"
class UserInteraction(Enum):
NONE = "N"
REQUIRED = "R"
class Scope(Enum):
UNCHANGED = "U"
CHANGED = "C"
class Integrity(Enum):
NONE = "N"
LOW = "L"
HIGH = "H"
class Availability(Enum):
NONE = "N"
LOW = "L"
HIGH = "H"
@dataclass
class CVSSVector:
version: CVSSVersion
attack_vector: AttackVector
attack_complexity: AttackComplexity
privileges_required: PrivilegesRequired
user_interaction: UserInteraction
scope: Scope
confidentiality: Integrity
integrity: Integrity
availability: Availability
class CVSSCalculator:
@staticmethod
def calculate_base_score(vector: CVSSVector) -> float:
if vector.version == CVSSVersion.CVSS30 or vector.version == CVSSVersion.CVSS31:
return CVSSCalculator._calculate_v31(vector)
return 0.0
@staticmethod
def _calculate_v31(vector: CVSSVector) -> float:
if vector.scope == Scope.CHANGED:
if vector.privileges_required == PrivilegesRequired.NONE:
iss = 1 - ((1 - vector.confidentiality.value * 0.56) *
(1 - vector.integrity.value * 0.56) *
(1 - vector.availability.value * 0.56))
elif vector.privileges_required == PrivilegesRequired.LOW:
iss = 1 - ((1 - vector.confidentiality.value * 0.56) *
(1 - vector.integrity.value * 0.56) *
(1 - vector.availability.value * 0.56))
else:
iss = 1 - ((1 - vector.confidentiality.value * 0.22) *
(1 - vector.integrity.value * 0.22) *
(1 - vector.availability.value * 0.22))
else:
if vector.privileges_required == PrivilegesRequired.NONE:
iss = 1 - ((1 - vector.confidentiality.value * 0.56) *
(1 - vector.integrity.value * 0.56) *
(1 - vector.availability.value * 0.56))
elif vector.privileges_required == PrivilegesRequired.LOW:
iss = 1 - ((1 - vector.confidentiality.value * 0.56) *
(1 - vector.integrity.value * 0.56) *
(1 - vector.availability.value * 0.56))
else:
iss = 1 - ((1 - vector.confidentiality.value * 0.27) *
(1 - vector.integrity.value * 0.27) *
(1 - vector.availability.value * 0.27))
if vector.attack_vector == AttackVector.NETWORK:
if vector.scope == Scope.CHANGED:
impact = 6.42 * iss
else:
impact = 8.22 * iss
elif vector.attack_vector == AttackVector.ADJACENT_NETWORK:
if vector.scope == Scope.CHANGED:
impact = 4.87 * iss
else:
impact = 6.12 * iss
elif vector.attack_vector == AttackVector.LOCAL:
if vector.scope == Scope.CHANGED:
impact = 3.25 * iss
else:
impact = 4.53 * iss
else:
if vector.scope == Scope.CHANGED:
impact = 1.22 * iss
else:
impact = 2.01 * iss
if vector.attack_complexity == AttackComplexity.LOW:
exploitability = 0.85
else:
exploitability = 0.62
if vector.privileges_required == PrivilegesRequired.NONE:
exploitability *= 0.85
elif vector.privileges_required == PrivilegesRequired.LOW:
exploitability *= 0.62
else:
exploitability *= 0.27
if vector.user_interaction == UserInteraction.NONE:
exploitability *= 0.85
else:
exploitability *= 0.62
score = min((1 - impact) * exploitability + impact, 0.915)
if iss == 0:
return 0.0
if vector.scope == Scope.CHANGED:
if score <= 0:
return 0.0
elif score < 0.1:
return 0.0
else:
return roundup(score * 10) / 10
else:
return roundup(score * 10) / 10
@staticmethod
def get_severity(score: float) -> str:
if score == 0:
return "NONE"
elif score < 4.0:
return "LOW"
elif score < 7.0:
return "MEDIUM"
elif score < 9.0:
return "HIGH"
else:
return "CRITICAL"
@staticmethod
def parse_vector_string(vector_string: str) -> CVSSVector:
parts = vector_string.split('/')
values = {p.split(':')[0]: p.split(':')[1] for p in parts}
return CVSSVector(
version=CVSSVersion.CVSS31,
attack_vector=AttackVector(values.get('AV', 'N')),
attack_complexity=AttackComplexity(values.get('AC', 'L')),
privileges_required=PrivilegesRequired(values.get('PR', 'N')),
user_interaction=UserInteraction(values.get('UI', 'N')),
scope=Scope(values.get('S', 'U')),
confidentiality=Integrity(values.get('C', 'N')),
integrity=Integrity(values.get('I', 'N')),
availability=Availability(values.get('A', 'N'))
)
def roundup(x):
return int(x + 0.9) if x % 1 != 0 else int(x)
```
### Vulnerability Database Manager
```python
import json
import sqlite3
from typing import List, Optional, Dict
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
class VulnerabilityStatus(Enum):
NEW = "new"
IN_PROGRESS = "in_progress"
RISK_ACCEPTED = "risk_accepted"
REMEDIATED = "remediated"
FALSE_POSITIVE = "false_positive"
@dataclass
class Vulnerability:
cve_id: str
title: str
description: str
cvss_score: float
cvss_vector: str
severity: str
cvss_version: str = "3.1"
published_date: datetime = None
modified_date: datetime = None
affected_products: List[str] = field(default_factory=list)
references: List[str] = field(default_factory=list)
status: VulnerabilityStatus = VulnerabilityStatus.NEW
asset_id: str = ""
remediation: str = ""
notes: str = ""
@dataclass
class Asset:
asset_id: str
hostname: str
ip_address: str
os: str
services: List[Dict] = field(default_factory=list)
criticality: str = "medium"
owner: str = ""
last_scanned: datetime = None
class VulnerabilityDatabase:
def __init__(self, db_path: str = "vuln_manager.db"):
self.db_path = db_path
self._init_db()
def _init_db(self):
with sqlite3.connect(self.db_path) as conn:
conn.execute("""
CREATE TABLE IF NOT EXISTS vulnerabilities (
cve_id TEXT PRIMARY KEY,
title TEXT NOT NULL,
description TEXT,
cvss_score REAL,
cvss_vector TEXT,
severity TEXT,
cvss_version TEXT,
published_date TEXT,
modified_date TEXT,
affected_products TEXT,
references TEXT,
remediation TEXT
)
""")
conn.execute("""
CREATE TABLE IF NOT EXISTS assets (
asset_id TEXT PRIMARY KEY,
hostname TEXT,
ip_address TEXT,
os TEXT,
services TEXT,
criticality TEXT,
owner TEXT,
last_scanned TEXT
)
""")
conn.execute("""
CREATE TABLE IF NOT EXISTS findings (
finding_id INTEGER PRIMARY KEY AUTOINCREMENT,
cve_id TEXT,
asset_id TEXT,
status TEXT,
detected_date TEXT,
remediation TEXT,
notes TEXT,
FOREIGN KEY (cve_id) REFERENCES vulnerabilities(cve_id),
FOREIGN KEY (asset_id) REFERENCES assets(asset_id)
)
""")
def add_vulnerability(self, vuln: Vulnerability):
with sqlite3.connect(self.db_path) as conn:
conn.execute("""
INSERT OR REPLACE INTO vulnerabilities
(cve_id, title, description, cvss_score, cvss_vector, severity,
cvss_version, published_date, modified_date, affected_products,
references, remediation)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
vuln.cve_id, vuln.title, vuln.description, vuln.cvss_score,
vuln.cvss_vector, vuln.severity, vuln.cvss_version,
vuln.published_date, vuln.modified_date,
json.dumps(vuln.affected_products),
json.dumps(vuln.references), vuln.remediation
))
def add_asset(self, asset: Asset):
with sqlite3.connect(self.db_path) as conn:
conn.execute("""
INSERT OR REPLACE INTO assets
(asset_id, hostname, ip_address, os, services, criticality, owner, last_scanned)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""", (
asset.asset_id, asset.hostname, asset.ip_address, asset.os,
json.dumps(asset.services), asset.criticality, asset.owner,
asset.last_scanned
))
def record_finding(self, cve_id: str, asset_id: str) -> int:
with sqlite3.connect(self.db_path) as conn:
cursor = conn.execute("""
INSERT INTO findings (cve_id, asset_id, status, detected_date)
VALUES (?, ?, 'new', ?)
""", (cve_id, asset_id, datetime.now().isoformat()))
return cursor.lastrowid
def get_open_findings(self) -> List[Dict]:
with sqlite3.connect(self.db_path) as conn:
cursor = conn.execute("""
SELECT f.finding_id, v.cve_id, v.title, v.severity, v.cvss_score,
a.hostname, a.ip_address, a.criticality, f.detected_date
FROM findings f
JOIN vulnerabilities v ON f.cve_id = v.cve_id
JOIN assets a ON f.asset_id = a.asset_id
WHERE f.status NOT IN ('remediated', 'false_positive', 'risk_accepted')
ORDER BY v.cvss_score DESC
""")
return [dict(zip([c[0] for c in cursor.description], row))
for row in cursor.fetchall()]
def get_vulnerability_summary(self) -> Dict:
with sqlite3.connect(self.db_path) as conn:
summary = {
"total": 0,
"by_severity": {"critical": 0, "high": 0, "medium": 0, "low": 0, "none": 0},
"avg_age_days": 0,
"by_status": {}
}
cursor = conn.execute("SELECT COUNT(*) FROM findings WHERE status NOT IN ('remediated', 'false_positive')")
summary["total"] = cursor.fetchone()[0]
for severity in summary["by_severity"]:
cursor = conn.execute("""
SELECT COUNT(*) FROM findings f
JOIN vulnerabilities v ON f.cve_id = v.cve_id
WHERE v.severity = ? AND f.status NOT IN ('remediated', 'false_positive')
""", (severity.upper(),))
summary["by_severity"][severity] = cursor.fetchone()[0]
return summary
```
### Vulnerability Prioritizer
```python
from typing import List, Dict
from dataclasses import dataclass
from datetime import datetime, timedelta
@dataclass
class PrioritizedVulnerability:
cve_id: str
title: str
cvss_score: float
asset_criticality: str
exploit_available: bool
exposure_factor: str
calculated_risk: float
priority: int
class VulnerabilityPrioritizer:
CVSS_WEIGHT = 0.4
ASSET_CRITICALITY_WEIGHT = 0.3
EXPLOIT_WEIGHT = 0.2
EXPOSURE_WEIGHT = 0.1
def __init__(self):
self.known_exploits = set()
def add_known_exploit(self, cve_id: str):
self.known_exploits.add(cve_id)
def calculate_risk_score(self, cvss_score: float, asset_criticality: str,
has_exploit: bool, is_exposed: bool) -> float:
normalized_cvss = cvss_score / 10.0
Ver en GitHub