Jenkins 認証情報の漏洩:CI/CD パイプラインに潜むセキュリティリスク

  1. Jenkins 認証情報の理解
  2. ビルドログ漏洩:最も一般的なミス
  3. スクリプトコンソール:管理バックドア
  4. API 漏洩:プログラマティックアクセス
  5. プラグインエコシステム:サードパーティのリスク
  6. 一般的な漏洩シナリオ
  7. 実際のインシデント:エンコードされた認証情報は安全ではない
  8. Jenkins 認証情報の保護
  9. 検出と対応
  10. 結論


Jenkins は、世界中の組織でビルド、テスト、デプロイを調整する、無数の CI/CD パイプラインのバックボーンとなっています。その柔軟性と豊富なプラグインエコシステムにより強力ですが、この柔軟性が認証情報漏洩の多くの経路を生み出しています。設定ミスのあるパイプラインや不注意なスクリプト一つで、データベースのパスワード、API キー、クラウド認証情報が、ビルドログにアクセスできる誰にでも漏洩する可能性があります。

本記事では、ビルドログでシークレットをエコーするような明白なミスから、プラグイン設定や API エンドポイントの微妙な脆弱性まで、Jenkins の認証情報が露出する様々な方法を探ります。Jenkins デプロイメントに潜む隠れたリスクと、CI/CD インフラストラクチャの機密認証情報を保護するための実用的な戦略を明らかにします。

📝 他の CI/CD システムにも適用

本記事は Jenkins に焦点を当てていますが、同じ認証情報漏洩リスクは他の CI/CD システムにも適用されます:

GitLab CI/CD

  • GitLab Runner ログがシークレットを露出する可能性
  • CI/CD 変数がジョブログでアクセス可能
  • Artifact とテストレポートに認証情報が含まれる可能性
  • API エンドポイントがパイプライン設定を露出

GitHub Actions

  • ワークフローログがエコーされたシークレットを露出
  • Actions がシークレットにアクセスし漏洩する可能性
  • Artifact に埋め込まれた認証情報が含まれる可能性
  • デバッグモードが露出リスクを増加

一般原則

  • ビルド/ジョブログが主要な露出ベクター
  • Artifact とレポートが認証情報を永続化
  • API アクセスが設定を露出
  • 議論された緩和戦略は普遍的に適用

Jenkins 認証情報の理解

漏洩リスクを深く掘り下げる前に、Jenkins が認証情報をどのように管理しているかを理解することが重要です。Jenkins は、シークレットを安全に保ちながら、パイプラインとジョブがアクセスできるように設計された集中型認証情報ストアを提供します。

Jenkins 認証情報システム

Jenkins の認証情報には、それぞれ特定の用途に設計されたいくつかのタイプがあります:

🔑 Jenkins 認証情報タイプ

ユーザー名とパスワード

  • 基本認証の認証情報
  • Git リポジトリ、artifact サーバー、API に使用
  • 暗号化されたキーバリューペアとして保存
  • 最も一般的な認証情報タイプ

シークレットテキスト

  • 単一のシークレット値(API キー、トークン)
  • クラウドプロバイダーの認証情報、webhook シークレットに使用
  • Jenkins 認証情報ストアで暗号化
  • シンプルだが多機能

シークレットファイル

  • シークレットを含む完全なファイル(証明書、kubeconfig)
  • 暗号化して保存、ビルド中に一時ファイルとして公開
  • SSH キー、TLS 証明書、設定ファイルに使用

SSH ユーザー名と秘密鍵

  • Git とリモートサーバーの SSH 認証
  • 秘密鍵を暗号化して保存
  • パスフレーズ保護をサポート

証明書

  • 相互 TLS のクライアント証明書
  • PKCS#12 キーストア
  • サービス間の安全な通信に使用

認証情報ストアは、$JENKINS_HOME/secrets/master.key に保存されたマスターキーを使用してシークレットを暗号化します。この暗号化は静的な認証情報を保護しますが、パイプラインで認証情報が使用されると、様々なチャネルを通じて漏洩しやすくなります。

認証情報のスコープとアクセス制御

Jenkins の認証情報には、使用できる場所を決定するスコープとアクセス制御があります:

🛡️ 認証情報のスコープ

システムスコープ

  • Jenkins システム(プラグイン、設定)のみが使用可能
  • ジョブやパイプラインからはアクセス不可
  • Jenkins 間通信、プラグイン設定に使用

グローバルスコープ

  • すべてのジョブとパイプラインで使用可能
  • 最も一般的に使用されるスコープ
  • ジョブが侵害された場合、漏洩リスクが最も高い

フォルダースコープ(Folders プラグイン使用時)

  • 特定のフォルダーに限定された認証情報
  • ジョブのサブセットへの露出を制限
  • グローバルスコープよりも優れた分離

アクセス制御

  • プラグインによるロールベースアクセス制御(RBAC)
  • 認証情報の権限とジョブの権限を分離
  • ユーザーは認証情報を表示せずに使用可能

これらのスコープを理解することは重要です。なぜなら、多くの認証情報漏洩は、そのような広範なアクセス権限を必要としないジョブでグローバル認証情報が使用される場合に発生するからです。

ビルドログ漏洩:最も一般的なミス

最も頻繁な認証情報漏洩は、ビルドログを通じて発生します。これは、Jenkins が保存しユーザーに表示するパイプライン実行の詳細な出力です。

偶発的な Echo と Print ステートメント

開発者は変数値を出力してパイプラインをデバッグすることがよくありますが、認証情報も単なる変数であることを忘れています:

// 宣言型パイプライン - 危険
pipeline {
    agent any
    environment {
        DB_PASSWORD = credentials('database-password')
    }
    stages {
        stage('Debug') {
            steps {
                // これはパスワードをビルドログに出力します!
                sh "echo Database password is: ${DB_PASSWORD}"
                
                // これも露出させます
                echo "Connecting with password: ${DB_PASSWORD}"
            }
        }
    }
}

ビルドログには以下が含まれます:

[Pipeline] sh
+ echo Database password is: SuperSecret123!
Database password is: SuperSecret123!
[Pipeline] echo
Connecting with password: SuperSecret123!

ビルドログにアクセスできる人(通常はすべての開発者を含む)は、パスワードを見ることができます。

環境変数のダンプ

もう一つの一般的なミスは、デバッグのためにすべての環境変数をダンプすることです:

pipeline {
    agent any
    environment {
        AWS_ACCESS_KEY = credentials('aws-access-key')
        AWS_SECRET_KEY = credentials('aws-secret-key')
    }
    stages {
        stage('Debug Environment') {
            steps {
                // 認証情報を含むすべての環境変数を露出
                sh 'env'
                
                // これも危険
                sh 'printenv'
                
                // これも認証情報を漏洩させる可能性
                sh 'set'
            }
        }
    }
}

出力は環境にロードされたすべての認証情報を明らかにします:

AWS_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

詳細なコマンド出力

一部のコマンドは認証情報を含む詳細な出力を生成します:

pipeline {
    agent any
    stages {
        stage('Deploy') {
            steps {
                withCredentials([usernamePassword(
                    credentialsId: 'api-credentials',
                    usernameVariable: 'API_USER',
                    passwordVariable: 'API_PASS'
                )]) {
                    // curl の -v フラグはヘッダーで認証情報を露出
                    sh 'curl -v -u ${API_USER}:${API_PASS} https://api.example.com/deploy'
                }
            }
        }
    }
}

詳細な出力には認証情報を含む Authorization ヘッダーが含まれます:

> GET /deploy HTTP/1.1
> Authorization: Basic QVBJVVNFUjpBUElQQVNT
> User-Agent: curl/7.68.0

base64 エンコードされていますが、これは簡単にデコードしてユーザー名とパスワードを明らかにできます。

⚠️ ビルドログ漏洩リスク

誰がビルドログにアクセスできるか

  • ジョブ読み取り権限を持つすべてのユーザー
  • 通常、開発チーム全体を含む
  • デフォルトでログは無期限に保存
  • Web UI と API を通じてアクセス可能

漏洩の永続性

  • ログは $JENKINS_HOME/jobs/*/builds/*/log に保存
  • 認証情報のローテーション後もアクセス可能
  • Jenkins バックアップに含まれる
  • ログ集約システムに転送される可能性

影響範囲

  • 露出した認証情報は本番システムにアクセス可能
  • Jenkins 環境を超えたアクセスを許可する可能性
  • 事後の漏洩検出が困難
  • 露出したすべての認証情報のローテーションが必要

スクリプトコンソール:管理バックドア

Jenkins は管理タスク用に Groovy スクリプトコンソールを提供していますが、この強力な機能は認証情報を抽出するために悪用される可能性があります。

直接的な認証情報アクセス

スクリプトコンソールへのアクセス権を持つユーザーは、認証情報ストアに直接クエリできます:

// スクリプトコンソール - すべての認証情報を抽出
import com.cloudbees.plugins.credentials.*
import com.cloudbees.plugins.credentials.domains.*

def creds = CredentialsProvider.lookupCredentials(
    StandardUsernamePasswordCredentials.class,
    Jenkins.instance,
    null,
    null
)

creds.each { c ->
    println "ID: ${c.id}"
    println "Username: ${c.username}"
    println "Password: ${c.password}"
    println "---"
}

このスクリプトは、すべてのユーザー名/パスワード認証情報を平文で出力します:

ID: database-credentials
Username: dbadmin
Password: SuperSecret123!
---
ID: api-credentials
Username: apiuser
Password: ApiKey789!
---

シークレットテキストの抽出

シークレットテキスト認証情報も同様に脆弱です:

import com.cloudbees.plugins.credentials.*
import org.jenkinsci.plugins.plaincredentials.*

def secrets = CredentialsProvider.lookupCredentials(
    StringCredentials.class,
    Jenkins.instance,
    null,
    null
)

secrets.each { s ->
    println "ID: ${s.id}"
    println "Secret: ${s.secret}"
    println "---"
}

出力:

ID: aws-secret-key
Secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
---
ID: slack-webhook
Secret: https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXX
---

SSH キーの抽出

SSH 秘密鍵も抽出できます:

import com.cloudbees.jenkins.plugins.sshcredentials.*

def sshCreds = CredentialsProvider.lookupCredentials(
    SSHUserPrivateKey.class,
    Jenkins.instance,
    null,
    null
)

sshCreds.each { c ->
    println "ID: ${c.id}"
    println "Username: ${c.username}"
    println "Private Key:"
    println c.privateKey
    println "---"
}

これは PEM 形式で完全な秘密鍵を出力し、不正アクセスに直接使用できます。

🚫 スクリプトコンソールのリスク

アクセス制御の問題

  • 「Overall/RunScripts」権限が必要
  • 通常、シニア開発者と DevOps に付与
  • 基本的な Jenkins にはスクリプト実行の監査証跡がない
  • スクリプトは完全な Jenkins 権限で実行

検出の課題

  • スクリプトコンソール使用の組み込みログがない
  • 認証情報抽出の検出が困難
  • 疑わしいスクリプト実行のアラートがない
  • 監査証跡には追加のプラグインが必要

緩和の複雑さ

  • 機能を失わずにスクリプトコンソールを無効化できない
  • アクセス制限は正当な管理に影響する可能性
  • スクリプトアクセス権を持つすべてのユーザーへの信頼が必要
  • Script Security プラグインの使用を検討

API 漏洩:プログラマティックアクセス

Jenkins は広範な REST および CLI API を提供しており、様々なエンドポイントを通じて意図せず認証情報を露出する可能性があります。

ジョブ設定 XML

ジョブ設定は API を通じて取得でき、XML に埋め込まれた認証情報を露出する可能性があります:

# ジョブ設定を取得
curl -u admin:token https://jenkins.example.com/job/my-pipeline/config.xml

認証情報がジョブ設定にハードコードされている場合(悪い慣行ですが驚くほど一般的):

<project>
  <builders>
    <hudson.tasks.Shell>
      <command>
        mysql -h db.example.com -u dbuser -pHardcodedPassword123! -e "SELECT * FROM users"
      </command>
    </hudson.tasks.Shell>
  </builders>
</project>

パスワードは XML レスポンスで平文で露出されます。

ビルド Artifact とテストレポート

認証情報はアーカイブされた artifact とテストレポートを通じて漏洩する可能性があります:

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                withCredentials([string(
                    credentialsId: 'api-key',
                    variable: 'API_KEY'
                )]) {
                    // 認証情報を設定ファイルに書き込む
                    sh 'echo "api_key: $API_KEY" > config.yaml'
                    
                    // ファイルをアーカイブ - 認証情報が artifact に!
                    archiveArtifacts artifacts: 'config.yaml'
                }
            }
        }
        stage('Test') {
            steps {
                // テストレポートに環境変数が含まれる
                sh 'pytest --verbose --capture=no'
                
                // JUnit レポートに出力で認証情報が含まれる可能性
                junit 'test-results/*.xml'
            }
        }
    }
}

🚫 Artifact とレポートの漏洩

アーカイブされた Artifact

  • 認証情報が埋め込まれた設定ファイル
  • シークレットを含むビルド出力
  • Web UI と API を通じてアクセス可能
  • クリーンアップしない限り無期限に保持
  • 開発者がデバッグのためにダウンロード

テストレポート

  • JUnit XML レポートが stdout/stderr をキャプチャする可能性
  • テスト失敗には通常環境コンテキストが含まれる
  • 詳細な出力を含む HTML レポート
  • ジョブ読み取り権限を持つすべてのユーザーがアクセス可能

ビルドパラメータと環境変数

API エンドポイントはビルドパラメータと環境変数を露出します:

# パラメータを含むビルド情報を取得
curl -u admin:token https://jenkins.example.com/job/my-pipeline/1/api/json?tree=actions[parameters[*]]

認証情報がパラメータとして渡された場合、レスポンスに認証情報の値が含まれる可能性があります:

{
  "actions": [{
    "parameters": [{
      "name": "DB_PASSWORD",
      "value": "SuperSecret123!"
    }]
  }]
}

認証情報プラグイン API

一部の認証情報プラグインは情報を漏洩する可能性のある API を露出します:

# すべての認証情報をリスト(一部のプラグインで許可)
curl -u admin:token https://jenkins.example.com/credentials/api/json

適切に設定されたプラグインは認証情報の値をマスクしますが、設定ミスやプラグインの脆弱性により露出する可能性があります。

⚠️ API 漏洩ベクター

設定のエクスポート

  • ジョブ設定に埋め込まれたシークレットが含まれる可能性
  • Jenkins に保存されたパイプライン定義(SCM ではない)
  • API キーを含むプラグイン設定
  • システム認証情報を含むグローバル設定

ビルド Artifact とレポート

  • アーカイブされた artifact 内の認証情報
  • シークレットを含む設定ファイル
  • 認証情報出力を含むテストレポート
  • artifact としてアーカイブされたログファイル
  • artifact API エンドポイントを通じてアクセス可能

プラグインの脆弱性

  • プラグインがカスタム API を通じて認証情報を露出する可能性
  • 認証情報処理のセキュリティ脆弱性
  • プラグインエンドポイントのアクセス制御不足
  • 既知の問題を持つ古いプラグイン

プラグインエコシステム:サードパーティのリスク

Jenkins の広範なプラグインエコシステムは、プラグイン固有の脆弱性と設定ミスを通じて、追加の認証情報漏洩リスクをもたらします。

Credential Binding プラグインの問題

Credential Binding プラグインは認証情報を安全に露出するように設計されていますが、悪用される可能性があります:

pipeline {
    agent any
    stages {
        stage('Deploy') {
            steps {
                withCredentials([string(
                    credentialsId: 'api-key',
                    variable: 'API_KEY'
                )]) {
                    // 認証情報をファイルに書き込むと露出
                    sh 'echo $API_KEY > /tmp/api-key.txt'
                    
                    // ファイルはビルド後もエージェント上に残る
                    sh 'curl -H "Authorization: Bearer $API_KEY" https://api.example.com'
                }
            }
        }
    }
}

認証情報はエージェント上に永続化されたファイルに書き込まれ、他のジョブやエージェントアクセス権を持つユーザーがアクセスできます。

Mask Passwords プラグイン:軍拡競争

Mask Passwords や Credentials Binding などの最新の Jenkins プラグインは、base64 エンコードされた値も処理して、ビルドログ内の認証情報を検出しマスクしようとします。しかし、人間の創造性は常に自動検出を打ち負かします:

pipeline {
    agent any
    options {
        maskPasswords()
    }
    environment {
        PASSWORD = credentials('my-password')
    }
    stages {
        stage('Test') {
            steps {
                // ログでマスク:****
                sh 'echo $PASSWORD'
                
                // 最新のプラグインはこれを検出してマスク可能
                sh 'echo $PASSWORD | base64'
                
                // しかし人間の創造性は回避方法を見つける:
                
                // 文字ごとの出力
                sh 'for i in $(seq 0 ${#PASSWORD}); do echo -n "${PASSWORD:$i:1}"; done'
                
                // 16進数エンコード
                sh 'echo $PASSWORD | xxd -p'
                
                // ROT13 または単純な暗号
                sh 'echo $PASSWORD | tr "A-Za-z" "N-ZA-Mn-za-m"'
                
                // 文字列の反転
                sh 'echo $PASSWORD | rev'
                
                // URL エンコード
                sh 'python3 -c "import urllib.parse; print(urllib.parse.quote(\"$PASSWORD\"))"'
                
                // 分割と連結
                sh 'P1=${PASSWORD:0:5}; P2=${PASSWORD:5}; echo "Part1: $P1, Part2: $P2"'
            }
        }
    }
}

⚠️ 検出の軍拡競争

プラグインの能力

  • 最新のプラグインは正確な認証情報マッチを検出
  • base64 エンコードされた認証情報を識別可能
  • 一般的なエンコードスキームのパターンマッチング
  • 新しい検出パターンで継続的に更新

人間の創造性が常に勝つ

  • 文字列を変換する無限の方法
  • カスタムエンコードスキーム
  • 文字操作と分割
  • 複数の変換による難読化
  • プラグインはすべての可能な変換を予測できない

根本的な問題

  • 検出は受動的、創造性は能動的
  • 新しい検出方法ごとに新しい回避技術が生まれる
  • 自動マスキングだけに頼ることはできない
  • 安全な設計による予防が不可欠
  • 教育とコードレビューが依然として重要

検出プラグインと回避技術の間の軍拡競争は、基本的な真実を示しています:認証情報を保護するために自動マスキングに頼ることはできません。唯一の信頼できるアプローチは、最初からビルドログに認証情報を露出させないことです。

Git プラグインの認証情報漏洩

Git 操作は様々な方法で認証情報を露出する可能性があります:

pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps {
                // 認証情報が URL に埋め込まれる
                git url: 'https://user:password@github.com/org/repo.git'
                
                // ビルドログと git 設定に表示される
                // エージェント上の .git/config に保存される
            }
        }
    }
}

認証情報は以下に表示されます:

  • チェックアウト中のビルドログ
  • エージェント上の .git/config ファイル
  • Git reflog と履歴
  • git 操作中のプロセスリスト

🚫 プラグイン関連のリスク

プラグインの脆弱性

  • プラグインに認証情報処理のバグがある可能性
  • セキュリティパッチが常に迅速に適用されるわけではない
  • 一部のプラグインは認証情報を安全でない方法で保存
  • カスタムプラグインはセキュリティレビューが不足している可能性

設定の複雑さ

  • 各プラグインには独自の認証情報処理がある
  • 設定ミスを導入しやすい
  • ドキュメントが不完全な場合がある
  • セキュリティのベストプラクティスが常に明確ではない

更新の課題

  • プラグインの更新が既存のジョブを壊す可能性
  • 互換性の懸念によりセキュリティ更新が遅延
  • 脆弱性の開示が発見に遅れる可能性
  • プラグインの自動セキュリティスキャンがない

一般的な漏洩シナリオ

認証情報が通常どのように露出するかを理解することで、組織は自身の Jenkins デプロイメントで同様の脆弱性を特定し防止できます。

公開アクセス可能な Jenkins インスタンス

適切な認証なしでインターネットに露出された Jenkins インスタンスは、重大な脆弱性を表します:

⚠️ 公開露出のリスク

一般的な設定ミス

  • デフォルトのセキュリティ設定が設定されていない
  • テスト用の「クイックセットアップ」が本番環境に残っている
  • ファイアウォールルールの設定ミスまたは回避
  • 認証なしでアクセス可能なスクリプトコンソール

潜在的な影響

  • すべての認証情報がスクリプトコンソールを通じて抽出可能
  • クラウドプロバイダーの認証情報によりリソースハイジャックが可能
  • データベース認証情報が顧客データを露出
  • ソースコードリポジトリへのアクセスが侵害
  • インフラストラクチャ全体の侵害の可能性

予防措置

  • Jenkins を直接インターネットに露出させない
  • すべてのアクセスに認証を要求
  • リモートアクセスには VPN または踏み台ホストを使用
  • 定期的なセキュリティ設定監査
  • 不正アクセス試行の監視

長期的なビルドログ漏洩

ビルド出力に記録された認証情報は長期間露出される可能性があります:

⚠️ ビルドログのリスク

発生方法

  • デバッグのために詳細ログが有効化
  • デバッグステートメントがパイプラインから削除されない
  • すべての開発者がログにアクセス可能
  • ログがバックアップとログ集約システムに含まれる
  • 自動認証情報スキャンがない

漏洩期間

  • 認証情報が数ヶ月または数年間露出される可能性
  • 不正な当事者によるアクセスがあったか判断困難
  • 大規模な認証情報ローテーションが必要
  • 完全なセキュリティ監査が必要になる可能性

緩和策

  • CI/CD パイプラインの定期的なセキュリティ監査
  • ログ内の認証情報の自動スキャン
  • セキュリティを考慮したビルドログ保持ポリシー
  • ログアクセスの最小権限の原則
  • 認証情報漏洩を防ぐためのパイプラインコードの定期的なレビュー

プラグインの脆弱性

Jenkins プラグインのセキュリティ脆弱性は、様々なベクターを通じて認証情報を露出する可能性があります:

🚫 プラグインセキュリティリスク

一般的な脆弱性パターン

  • 認証情報を露出する未認証 API エンドポイント
  • 認証情報取得のアクセス制御不足
  • プラグインデータ内の安全でない認証情報保存
  • エラーメッセージによる情報漏洩

組織的課題

  • プラグインの更新が既存のジョブを壊す可能性
  • 互換性テストによりセキュリティパッチが遅延
  • 使用中の脆弱なプラグインを組織が認識していない
  • プラグインの自動脆弱性スキャンがない

ベストプラクティス

  • インストール済みプラグインのインベントリを維持
  • Jenkins セキュリティアドバイザリを購読
  • 迅速なパッチプロセスを実装
  • 選択基準でプラグインセキュリティを考慮
  • Jenkins インスタンスの定期的な脆弱性スキャン

実際のインシデント:エンコードされた認証情報は安全ではない

本番環境で認証情報の漏洩を発見すると、理論が現実になります。私は、同僚がシステムのエンコーディングが保護してくれると考えて、Jenkins に認証情報を保存したときに、これを直接経験しました。

Jenkins ジョブは正常に実行されましたが、ビルドログには彼のエンコードされた認証情報が含まれており、ログにアクセスできる誰もが見ることができました。エンコーディングは誤った安全感を提供しました。base64 や類似のスキームは簡単に逆変換できます。訓練されていない目には、それはランダムな文字列のように見えましたが、実際には彼のユーザー名とパスワードであり、1つのデコードコマンドで平文に戻すことができました。

漏洩を発見したとき、私の同僚は休暇中でした。認証情報は複数のシステムにわたって広範なアクセス権を持っており、状況は危機的でした。彼の帰りを待つことはできませんでした。1時間ごとに不正アクセスのリスクが増加していました。

私はすぐに彼のマネージャーにエスカレーションしました。会話は不快でしたが必要でした:「あなたのチームメンバーの認証情報が Jenkins ログに露出しています。今すぐローテーションする必要があります。」彼のマネージャーは深刻さを理解し、迅速に行動し、アカウントをロックしてパスワードリセットを開始しました。セキュリティチームは、漏洩期間中の疑わしい活動についてアクセスログをレビューしました。

このインシデントは、いくつかの痛ましい真実を浮き彫りにしました:

🚨 実際の漏洩からの教訓

エンコーディングは暗号化ではない

  • Base64、16進数、URL エンコーディングは可逆変換
  • ログアクセス権を持つ誰でも認証情報をデコード可能
  • Jenkins 認証情報マスキングはすべてのエンコーディングスキームをキャッチできない
  • 開発者はしばしば違いを誤解している

漏洩は発見後も持続

  • ログは認証情報ローテーション後もアクセス可能
  • 漏洩期間中に誰がログにアクセスしたか不明
  • バックアップとログ集約システムがコピーを保持
  • 完全な監査証跡の再構築は通常不可能

組織への影響

  • 緊急対応が通常業務を中断
  • 影響を受けた個人への信頼への影響
  • すべてのパイプラインのより広範なセキュリティレビューが必要

アクセス権がリスクを増幅

  • 広範な権限を持つ認証情報はより大きな爆発半径を生む
  • 単一の漏洩が複数のシステムを危険にさらす可能性
  • 最小権限の原則が重要になる
  • サービスアカウントはユーザーアカウントと同じ保護が必要

このインシデントにより、Jenkins セキュリティプラクティスの包括的なレビューが強制されました。自動認証情報スキャンを実装し、認証情報の機密性に基づいてログアクセスを制限し、エンコーディングがセキュリティを提供しないことを強調するセキュリティトレーニングを実施しました。最も重要なことは、将来のインシデントのための明確なエスカレーション手順を確立したことです。誰が影響を受けているか、または彼らが利用可能かどうかに関係なく、誰も認証情報漏洩の報告をためらうべきではありません。

露出した認証情報を発見したら、すぐに行動してください。

Jenkins 認証情報の保護

認証情報漏洩を防ぐには、Jenkins 設定、パイプライン設計、運用プラクティス全体にわたる多層防御が必要です。

安全なパイプラインプラクティス

認証情報漏洩を最小限に抑えるパイプラインを設計:

pipeline {
    agent any
    stages {
        stage('Deploy') {
            steps {
                withCredentials([usernamePassword(
                    credentialsId: 'api-credentials',
                    usernameVariable: 'API_USER',
                    passwordVariable: 'API_PASS'
                )]) {
                    // エコーせずに認証情報を使用
                    sh '''
                        # コマンドエコーを無効化
                        set +x
                        
                        # コマンドで認証情報を使用
                        curl -s -u "$API_USER:$API_PASS" https://api.example.com/deploy
                        
                        # 後続のコマンドのためにエコーを再有効化
                        set -x
                    '''
                }
            }
        }
    }
}

主要なプラクティス:

  • 認証情報使用時は set +x でコマンドエコーを無効化
  • 環境変数の出力を避ける
  • withCredentials ブロックで認証情報のスコープを制限
  • 認証情報をファイルに書き込まない

認証情報スコープの制限

フォルダースコープの認証情報を使用して可用性を制限:

✅ 認証情報スコープのベストプラクティス

Folder プラグインの使用

  • チームまたはプロジェクトごとにジョブをフォルダーに整理
  • 特定のフォルダーにスコープされた認証情報を作成
  • 他のフォルダーのジョブが認証情報にアクセスするのを防ぐ
  • 侵害されたジョブの爆発半径を削減

最小権限の原則

  • ユースケースごとに個別の認証情報を作成
  • 複数のジョブで認証情報を再利用しない
  • 可能な限り読み取り専用認証情報を使用
  • 定期的に認証情報をローテーション

認証情報の命名

  • スコープと目的を示す説明的な ID を使用
  • 「password」や「api-key」などの汎用名を避ける
  • 名前に環境を含める(prod-db-password vs dev-db-password)
  • 認証情報の目的と承認された使用を文書化

アクセス制御と監査

厳格なアクセス制御と監視を実装:

🔒 アクセス制御措置

ロールベースアクセス制御

  • Role Strategy または Folder Authorization プラグインを使用
  • 認証情報管理とジョブ実行権限を分離
  • スクリプトコンソールアクセスを最小限のユーザーに制限
  • ユーザー権限の定期的なレビュー

監査ログ

  • 認証情報アクセスログのために Audit Trail プラグインを有効化
  • スクリプトコンソール使用を監視
  • 通常パターン外の認証情報取得にアラート
  • Jenkins ログを SIEM システムと統合

ビルドログセキュリティ

  • ビルドログ保持期間を制限
  • 認証情報の機密性に基づいてログアクセスを制限(下記の注意事項参照)
  • ログ内の認証情報の自動スキャンを実装
  • 機密パイプラインのログ暗号化を検討

ビルドログアクセスの注意事項

  • ジョブ所有者は通常、ジョブで使用される認証情報を所有していない
  • 本番認証情報は通常セキュリティチームが所有
  • ログアクセス権を持つジョブ所有者は露出した認証情報を表示可能
  • 解決策:ジョブ所有者ではなく認証情報所有者にログアクセスを制限
  • 代替案:自動認証情報マスキング(不完全、前のセクション参照)
  • 最良のアプローチ:ログ内の認証情報露出を完全に防止

認証情報管理とジョブ実行の分離

重要なセキュリティプラクティスの一つは、誰が認証情報を管理できるかと誰がジョブで使用できるかを分離することです。この分離により、開発者は認証情報の値を表示せずにパイプラインで使用できます。

権限分離は重要な防御層ですが、完璧ではありません。ジョブを設定できるパイプライン管理者は、認証情報を露出するパイプラインを書くことができます。真の保護は、権限分離を安全なパイプラインプラクティス、コードレビュー、自動認証情報スキャンと組み合わせることから生まれます。

外部シークレット管理:万能薬ではない

外部シークレット管理システムはリスクを軽減しますが、漏洩ベクターを排除するものではありません:

// HashiCorp Vault の使用
pipeline {
    agent any
    stages {
        stage('Deploy') {
            steps {
                script {
                    // 実行時に Vault からシークレットを取得
                    def secrets = vault(
                        path: 'secret/data/myapp',
                        engineVersion: 2
                    )
                    
                    // ログに記録すればシークレットは依然として露出!
                    sh "echo API Key: ${secrets.api_key}"  // 依然として危険
                    
                    // シークレットは依然として artifact で露出
                    sh "echo 'key: ${secrets.api_key}' > config.yaml"
                    archiveArtifacts 'config.yaml'  // 依然として露出
                    
                    // 正しい使用法 - ログや artifact なし
                    sh """
                        set +x
                        curl -H "Authorization: Bearer ${secrets.api_key}" \
                             https://api.example.com/deploy
                    """
                }
            }
        }
    }
}

⚠️ 外部シークレットはすべての漏洩を防げない

外部シークレットが解決すること

  • 認証情報が Jenkins に静的に保存されない
  • 集中型認証情報管理とローテーション
  • シークレットアクセスの監査ログ
  • 短期間の動的認証情報
  • Jenkins が侵害された場合の爆発半径の削減

外部シークレットが解決しないこと

  • ビルドログ漏洩(エコーされればシークレットは依然としてログに記録)
  • Artifact 漏洩(ファイルに書き込まれればシークレットは依然としてアーカイブ)
  • テストレポート漏洩(シークレットは依然としてテスト出力に)
  • スクリプトコンソールアクセス(シークレットはメモリ内で依然としてアクセス可能)
  • API 漏洩(シークレットは依然としてビルドパラメータ/環境に)

根本的な真実

  • 外部シークレット管理はシークレットが保存される場所を変更
  • パイプラインでシークレットがどのように使用されるかは変更しない
  • すべての漏洩ベクター(ログ、artifact、レポート)は依然として存在
  • 安全なパイプラインプラクティスは依然として不可欠
  • セキュリティのために外部シークレットだけに頼ることはできない

✅ 外部シークレット管理の利点

安全なプラクティスと組み合わせた場合

  • 集中制御と監査ログ
  • 動的で短期間の認証情報
  • より簡単なローテーションと取り消し
  • 関心の分離
  • Jenkins 攻撃面の削減

人気のソリューション

  • HashiCorp Vault
  • AWS Secrets Manager
  • Azure Key Vault
  • Google Secret Manager
  • CyberArk

重要な要件

  • 安全なパイプライン設計と組み合わせる必要がある
  • ログ、artifact、レポートの漏洩を排除
  • 外部シークレットは層であり、完全なソリューションではない

検出と対応

予防措置があっても、認証情報漏洩の検出と対応は重要です。

自動認証情報スキャン

露出した認証情報を検出するための自動スキャンを実装:

🔍 スキャン戦略

ビルドログスキャン

  • 一般的な認証情報形式の正規表現パターン
  • API キーパターン(AWS、GitHub、Slack など)
  • ログ内のパスワードのような文字列
  • Base64 エンコードされた認証情報

設定スキャン

  • ハードコードされたシークレットのジョブ設定をスキャン
  • Jenkins 内のパイプライン定義をチェック
  • プラグイン設定を監査
  • グローバル Jenkins 設定をレビュー

ツールと統合

  • リポジトリスキャン用の git-secrets
  • 認証情報検出用の truffleHog
  • Jenkins 固有パターン用のカスタムスクリプト
  • 自動チェックのための CI/CD パイプラインとの統合

インシデント対応手順

認証情報漏洩インシデントのための明確な手順を確立:

🚨 インシデント対応ステップ

即時アクション

  1. 露出した認証情報とそのスコープを特定
  2. 侵害された認証情報を即座にローテーション
  3. 不正使用のアクセスログをレビュー
  4. ローテーションが不可能な場合は侵害されたアカウントを無効化

調査

  1. 漏洩期間とアクセススコープを決定
  2. 露出した認証情報にアクセスできた人を特定
  3. 不正アクセスの兆候をチェック
  4. タイムラインと影響を文書化

修復

  1. 漏洩の根本原因を修正
  2. 再発防止のためにパイプラインを更新
  3. 追加の制御を実装
  4. 影響を受けたチームにセキュリティトレーニングを実施

事後

  1. 学んだ教訓を文書化
  2. セキュリティ手順を更新
  3. 組織内で知識を共有
  4. フォローアップレビューをスケジュール

結論

Jenkins 認証情報漏洩は、現代の CI/CD パイプラインにおける重大なセキュリティリスクを表します。Jenkins を強力にする柔軟性—Groovy スクリプト、広範なプラグイン、詳細なログ—は、認証情報が漏洩する多数の経路も生み出します。ビルドログでパスワードをエコーするような明白なミスから、プラグイン API の微妙な脆弱性まで、攻撃面は広範で常に進化しています。

最も一般的な漏洩ベクターは依然としてビルドログであり、開発者はデバッグ中または詳細なコマンド出力を通じて意図せず認証情報を出力します。これらのログはデフォルトで無期限に保持され、すべての開発者がアクセスでき、ログ集約システムに転送されることが多く、漏洩を倍増させます。スクリプトコンソールは管理権限を提供しますが、アクセス権を持つ誰でも直接認証情報を抽出できます。API エンドポイントは、ジョブ設定、ビルドパラメータ、プラグイン固有の脆弱性を通じて認証情報を露出する可能性があります。

一般的な漏洩シナリオは、不十分な認証情報保護の深刻な結果を示しています。デフォルトのセキュリティ設定を持つ公開アクセス可能な Jenkins インスタンスは、インフラストラクチャ全体の侵害につながる可能性があります。長期間認証情報を含むビルドログは、組織を広範な監査を必要とする未知のリスクにさらします。プラグインの脆弱性は数千のインストールに影響を与える可能性があり、多くの組織は互換性の懸念によりパッチの適用が遅れています。

保護には多層防御が必要です。安全なパイプラインプラクティスは、withCredentials ブロックの慎重な使用、コマンドエコーの無効化、認証情報出力の回避を通じて認証情報漏洩を最小限に抑えます。認証情報スコープは、どのジョブが特定の認証情報にアクセスできるかを制限することで爆発半径を制限します。厳格なアクセス制御と包括的な監査ログにより、疑わしい活動を検出できます。HashiCorp Vault のような外部シークレット管理システムは、動的で短期間の認証情報と集中制御を提供しますが、ログ、artifact、レポートを通じた漏洩は排除できません—シークレットがどこに保存されていても、安全なパイプライン設計は依然として不可欠です。

検出と対応能力も同様に重要です。ビルドログと設定の自動スキャンにより、攻撃者が発見する前に露出した認証情報を特定できます。明確なインシデント対応手順により、侵害された認証情報の迅速なローテーションと、潜在的な不正アクセスの徹底的な調査が保証されます。Jenkins 設定、プラグイン、パイプラインの定期的なセキュリティ監査は、脆弱性が悪用される前に特定するのに役立ちます。

「コードとしてのセキュリティ」とインフラストラクチャ自動化のトレンドにより、Jenkins セキュリティはますます重要になっています。組織が CI/CD システムにより多くの認証情報を統合するにつれて、漏洩の影響も増大しています。最小権限の原則は、すべての認証情報の決定を導くべきです:フォルダースコープの認証情報を使用し、ユースケースごとに個別の認証情報を作成し、読み取り専用アクセスを優先し、定期的にローテーションします。

Jenkins に認証情報を保存する前に、自問してください:この認証情報は Jenkins に必要ですか、それとも外部シークレットマネージャーから取得できますか?誰がこの認証情報にアクセスする必要があり、より狭くスコープできますか?この認証情報が露出した場合、どのように検出しますか?ローテーション戦略は何ですか?これらの質問への答えが、認証情報管理戦略を導き、CI/CD パイプラインでの次の認証情報漏洩インシデントを防ぐのに役立つはずです。

シェア