Files
vulncheck/alembic/versions/034_add_risk_dimensions.py
T
vulncheck c3a75e7a77 feat(risk): Asset Risk Dimensions — high-value-target scoring + exposure rebalance + URS
Tester: the port-based exposure score put nearly every Windows host at 100
(no separation), and the thing that actually matters — whether a host runs
a crown-jewel role enabling lateral movement / domain takeover — wasn't
captured.

- Migration 034 + model: assets.high_value_score (0-100) + risk_dimensions
  (JSON roles) + _updated_at.
- app/services/risk_dimensions_service.py: detect_risk_dimensions(ports,
  packages) → roles from syscollector ports (port + process) and installed
  packages: Domain Controller, ADCS/CA, backup servers, SW-distribution,
  Exchange, WSUS, MSSQL, DNS, DHCP, WinRM. Score = max(weight) + 0.3·rest
  (cap 100). risk_factor() maps it to a URS band (>=90→1.5 … else 1.0).
- exposure_service: rebalanced port weights — baseline Windows
  (SMB/MSRPC/NetBIOS/WinRM) now LOW; real remote-control/cleartext
  exposures (Telnet/VNC/RDP/FTP) stay HIGH. Risk detection runs in the same
  pass (reuses fetched ports + one get_packages call).
- urs_service: URS uses max(operator criticality factor, role factor) — a
  DC/ADCS host rises to critical weighting even at criticality=normal;
  operator can still set higher. criticality field untouched.
- assets API: high_value_score + risk_dimensions in the response + sortable;
  Assets page gets a "Risk" column with score + role badges.

Verified detection: DC(88+389)→100, SQL pkg+WinRM→79, plain Win→0,
Exchange+Veeam→100. Migration 034 required: alembic upgrade head.
Roles need Wazuh syscollector (ports+packages); Nessus/Intune-only → v2.
2026-06-16 13:23:16 +02:00

44 lines
1.3 KiB
Python

"""Add asset risk-dimension (high-value-target) columns
Revision ID: 034
Revises: 033
Create Date: 2026-06-16 09:00:00.000000
"Risk Dimensions": crown-jewel role detection (Domain Controller, ADCS,
SQL, Exchange, WSUS, backup, ...) computed alongside network exposure and
fed into the URS. Stores a 0-100 high_value_score + the detected roles.
Idempotent — ADD COLUMN IF NOT EXISTS.
"""
from alembic import op
revision = "034"
down_revision = "033"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.execute("""
ALTER TABLE assets
ADD COLUMN IF NOT EXISTS high_value_score DOUBLE PRECISION,
ADD COLUMN IF NOT EXISTS risk_dimensions TEXT,
ADD COLUMN IF NOT EXISTS risk_dimensions_updated_at TIMESTAMP;
""")
op.execute("""
CREATE INDEX IF NOT EXISTS ix_assets_high_value_score
ON assets (high_value_score)
WHERE high_value_score > 0;
""")
def downgrade() -> None:
op.execute("DROP INDEX IF EXISTS ix_assets_high_value_score;")
op.execute("""
ALTER TABLE assets
DROP COLUMN IF EXISTS high_value_score,
DROP COLUMN IF EXISTS risk_dimensions,
DROP COLUMN IF EXISTS risk_dimensions_updated_at;
""")