脆弱性の優先順位付けは、脆弱性の相対的なリスクと修復順序を評価し、最高優先度から最低優先度までランク付けする重要なフェーズです。 前回の記事では、 について説明しました。この記事では、修復の優先度を評価するための独自のアプローチを説明し、この機能をBudibase プラットフォームに統合した方法を説明します。 Budibase を用いてセキュリティ脆弱性を管理する方法 修復プロセスでは、次のようないくつかの課題がしばしば発生します。 さまざまな資産にわたって、リスク レベルが異なる脆弱性が多数存在します。 侵入テストで頻繁に明らかになるように、優先度を決定するために CVSS リスク スコアのみに頼ることは必ずしも効果的ではありません。 一部の脆弱性は、アプリケーション開発プロセスの設計が不十分であったり、場合によってはベンダーのサポートが不足していたりするため、すぐに修復できないことがあります。 理論と優先順位の指標 脆弱性をスキャンした後は、結果を分析し、修復の優先順位を設定することが重要です。定期的にパッチを適用することで、ほとんどの脆弱性を最小限の労力で解決できます。 ただし、特定の脆弱性を綿密に調査し、関連するリスクを評価する必要がある場合もあります。即時の修復が不可能な場合は、代替対策の導入を検討してください。例えば、WebアプリケーションでSQLインジェクションの脆弱性が見つかり、すぐに修正できない場合は、その脆弱性に関連するシグネチャを備えたWebアプリケーションファイアウォール(WAF)を代替対策として活用するといった方法があります。 評価の目的で、優先度の高い脆弱性を定量的に評価し、同僚向けに .csv 形式でリストをエクスポートできるインターフェースを Budibase に作成しました。 私がフィルターを構築した主な指標の概要を説明します。 :脆弱性が修正されない期間が長ければ長いほど、将来的にエクスプロイトが出現する可能性が高くなります。しかし、時間が経つにつれて、より適切な対策やパッチが利用可能になるのが一般的です。逆に、脆弱性が最近公開された場合、チームによる即時のパッチ適用は期待できません。そこで、X日未満の脆弱性を除外するフィルターを追加しました。 脆弱性公開からの期間 : このメトリックは、資産が侵害された場合の重要度を評価します。 資産の重要度 :この要素は、資産が管理されていないネットワークセグメントからどの程度露出しているか、そしてその配置に基づいてどのような補償制御が適用されるかを判断するのに役立ちます。この指標と重要度を組み合わせました。境界に位置する資産は、高優先度としてフラグ付けされます。 資産の配置場所 :これは、脆弱性が現在悪用されているかどうかを示します。ベンダーまたは脅威インテリジェンスプロバイダーがトレンドスコアを提供している場合は、このパラメータをフィルターで利用できます。 脆弱性のトレンド : これは、ローカルとリモートのエクスプロイト可能性などの CVSS メトリックから導出されます。 エクスプロイト ベクトル : これは、脆弱性に対して機能するエクスプロイトが既に存在するかどうかを示します。 エクスプロイトの可用性 : これは、標準の CVSS メトリックに従った基本的な重大度評価を反映します。 CVSS 重大度 : 脆弱性を修正するためのベンダーの修正プログラムまたは更新が存在するかどうかを示します。 パッチの可用性 これらの指標は総合的に、脆弱性の潜在的な影響と対応戦略の効率に基づいて、脆弱性の優先順位付けに役立ちます。 Budibase での優先順位付けフィルタの実装 この実装の主な目的は、フィルターパラメータが変更されるたびにダッシュボードと関連データが自動的に更新されるようにすることです。これにより、パッチ適用を担当する同僚は、最も関連性の高い結果をエクスポートできるようになります。 Budibaseでは、フィルタリングはUIフィルター要素を通じて行われます。選択された値は、バインディングを使用して変数としてSQLクエリに渡されます。これらの変数はチャート要素の設定で設定されます。例に示すように、バインディングは下の画像の中央に表示されます。 SQLクエリでは、適切な場所に二重中括弧({{ var }})を使用して変数が挿入されます。これにより、完全に機能するSQLクエリが保証されます。 SQL クエリは、データベース接続セクションの「データ」タブに作成されます。 ここで、SQL クエリのバインディングを定義し、フィルターが空の場合や何も選択されていない場合のデフォルト値を設定します。 ダッシュボード作成のための優先順位付けされたSQLクエリの例 ここでは、優先順位付けフィルターを備えたダッシュボードの作成に使用できる SQL クエリの例をいくつか示します。 ダッシュボード1: 最も脆弱な資産トップ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; ダッシュボード2: 脆弱なサービストップ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; 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; ダッシュボード 3: アクティブな CVE トップ 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; すべてがもたらすもの 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; 最終的に、この設定は、最も重大な脆弱性に基づいて、最も問題のある資産やサービスを特定するための、シンプルでありながら効果的なツールとなりました。また、必要に応じてこの情報を簡単にエクスポートすることもできます。 高価な脆弱性管理(VM)プラットフォームの予算がないからといって、脆弱性を効果的に優先順位付けできないわけではありません。多くの商用VMソリューションは、特定のインフラストラクチャに必要なレベルの優先順位付けの柔軟性に欠けている可能性があります。 まとめ: 次の記事では、 について説明し、それを Budibase に実装する方法を示し、優先順位付けされた脆弱性のリストをエクスポートする機能を追加します。 エクスプロイト予測スコアリング システム (EPSS) ぜひあなたのご意見をお聞かせください: 仕事で脆弱性の優先順位付けを使用していますか? 重要な資産をどのように追跡しますか?