LESSON 30分

ストーリー

高橋アーキテクト
Log4Shell事件を覚えているか?

高橋アーキテクトが問いかけました。

高橋アーキテクト
2021年末、Javaのログライブラリ Log4j に深刻な脆弱性が見つかった。世界中のシステムが影響を受けた。問題は、多くの企業が”自分のシステムにLog4jが含まれているかどうかさえ分からなかった”ことだ
あなた
依存関係が多すぎて…
高橋アーキテクト
そう。直接使っていなくても、間接的な依存として含まれていることがある。だからこそSBOM(ソフトウェア部品表)が必要なんだ

SBOMとは

SBOM(Software Bill of Materials)は、ソフトウェアに含まれる全てのコンポーネント(ライブラリ、フレームワーク、ツール)の一覧です。製造業のBOM(部品表)のソフトウェア版です。

SBOMに含まれる情報

項目説明
コンポーネント名パッケージ名express
バージョン使用バージョン4.18.2
ライセンスOSS ライセンスMIT
サプライヤー提供元expressjs
依存関係依存パッケージbody-parser, cookie-parser
ハッシュパッケージの完全性検証SHA-256

SBOMのフォーマット

主要なフォーマット

フォーマット策定者特徴
SPDXLinux FoundationISO標準(ISO/IEC 5962
CycloneDXOWASPセキュリティに焦点、軽量
SWIDISO/IECソフトウェアの識別に特化
// CycloneDX形式のSBOMの例(簡略化)
interface CycloneDXBom {
  bomFormat: "CycloneDX";
  specVersion: "1.5";
  version: 1;
  metadata: {
    timestamp: string;
    tools: { vendor: string; name: string; version: string }[];
    component: { type: "application"; name: string; version: string };
  };
  components: {
    type: "library";
    name: string;
    version: string;
    purl: string; // Package URL(一意な識別子)
    licenses: { license: { id: string } }[];
    hashes: { alg: string; content: string }[];
  }[];
  dependencies: {
    ref: string;
    dependsOn: string[];
  }[];
}

SBOMの生成

Node.jsプロジェクトでのSBOM生成

# CycloneDX CLI でSBOM生成
npx @cyclonedx/cyclonedx-npm --output-file sbom.json

# syft(Anchore)でコンテナイメージのSBOM生成
syft myapp:latest -o cyclonedx-json > container-sbom.json
// CI/CDパイプラインでのSBOM生成
interface SbomPipelineConfig {
  // ビルド時にSBOMを自動生成
  generateOnBuild: true;

  // 生成したSBOMの保存先
  storage: {
    type: "s3";
    bucket: "sbom-artifacts";
    path: "sboms/${project}/${version}/sbom.json";
  };

  // SBOMの検証
  validation: {
    // 既知の脆弱性チェック
    vulnerabilityCheck: true;
    // ライセンス互換性チェック
    licenseCheck: true;
    // 禁止パッケージのチェック
    blocklist: ["event-stream@3.3.6"]; // 既知のマルウェア
  };
}

SBOMの活用

1. 脆弱性の迅速な特定

// SBOMを使った脆弱性チェック
const checkVulnerabilities = async (sbom: CycloneDXBom): Promise<Vulnerability[]> => {
  const vulnerabilities: Vulnerability[] = [];

  for (const component of sbom.components) {
    // NVD(National Vulnerability Database)でチェック
    const cves = await queryNVD(component.name, component.version);
    if (cves.length > 0) {
      vulnerabilities.push({
        component: component.name,
        version: component.version,
        cves: cves.map(c => ({
          id: c.id,
          severity: c.severity,
          description: c.description,
        })),
      });
    }
  }

  return vulnerabilities;
};

2. ライセンスコンプライアンス

// ライセンス互換性チェック
const incompatibleLicenses = ["GPL-3.0", "AGPL-3.0"]; // 商用利用に制約

const checkLicenseCompliance = (sbom: CycloneDXBom): LicenseIssue[] => {
  return sbom.components
    .filter(c => c.licenses.some(l =>
      incompatibleLicenses.includes(l.license.id)
    ))
    .map(c => ({
      component: c.name,
      version: c.version,
      license: c.licenses[0].license.id,
      risk: "商用プロジェクトでの使用に制約がある可能性",
    }));
};

3. サプライチェーン攻撃の検知

// パッケージの完全性検証
const verifyIntegrity = async (sbom: CycloneDXBom): Promise<IntegrityResult[]> => {
  const results: IntegrityResult[] = [];

  for (const component of sbom.components) {
    const registryHash = await getRegistryHash(component.purl);
    const sbomHash = component.hashes.find(h => h.alg === "SHA-256")?.content;

    if (registryHash !== sbomHash) {
      results.push({
        component: component.name,
        status: "MISMATCH",
        message: "ハッシュ値がレジストリと一致しません。改ざんの可能性があります",
      });
    }
  }

  return results;
};

まとめ

ポイント内容
SBOMソフトウェアの全コンポーネント一覧
フォーマットCycloneDX(OWASP)が推奨
生成CI/CDで自動生成・保存
活用脆弱性チェック、ライセンス確認、改ざん検知

チェックリスト

  • SBOMの概念と目的を理解した
  • 主要なSBOMフォーマットを把握した
  • SBOMの生成方法を理解した
  • SBOMの3つの活用方法を把握した

次のステップへ

次は「脆弱性管理とパッチ戦略」を学びます。SBOMで特定した脆弱性をどのように管理し、パッチを適用するかを学びましょう。


推定読了時間: 30分