
Seal Securityの例 — 脆弱なMavenアプリ(SnakeYAML CVE-2022-1471)をシールド版に修正済み。GitHub Actions + Jenkins統合。
既知のCVEを、脆弱な依存関係を封印(sealed)(バックポートされたドロップイン版)バージョンに置き換えることで修復する方法を、エンドツーエンドで実証するために使用される、最小限で意図的に脆弱な Spring Boot アプリケーションです。Seal Security がどのように修復するかを示します。宣言された座標やコードを変更する必要はありません。
これは、CI/CD における Seal CLI のフロントからバックまでのスモークテストとして設計されています。アプリを実行し、実際のエクスプロイトをトリガーし、Seal を実行して、同じエクスプロイトがブロックされることを確認します。
| エコシステム | Java / Maven |
| 脆弱なパッケージ | org.yaml:snakeyaml:1.33 |
| CVE | CVE‑2022‑1471 — SnakeYAML Constructor のデシリアライゼーション → リモートコード実行(CVSS 9.8) |
| 封印(修正済み)バージョン | Seal の Maven レジストリからの snakeyaml 1.33+sp1 |
| 統合 | ビルドステップとしての Seal CLI — GitHub Actions と Jenkins の両方で紹介 |
このプロジェクトは、他のよく知られた脆弱な依存関係(jackson-databind 2.13.1、commons-text 1.9、spring-core/web 5.3.26、json-smart 2.4.8、commons-lang3 3.12.0、spring-boot 2.7.18)も宣言しており、Seal はそれぞれ封印ビルドにも修復します。
ウェルカムページは name を受け取り、SnakeYAML のデフォルトコンストラクタで解析します:
Yaml yaml = new Yaml();
Object parsed = yaml.load(name); // SnakeYAML 1.33 — CVE-2022-1471
SnakeYAML のデフォルトの Constructor は、YAML 内で指定された任意の Java 型をインスタンス化します — これは CVE‑2022‑1471 の背後にあるオブジェクトインジェクションのプリミティブです。javax.script.ScriptEngineManager(古典的な RCE ガジェットチェーンのエントリポイント)を指定するペイロードは、パーサーが攻撃者の指定した任意のクラスを構築することを証明するのに十分です。
通常のリクエスト
/?name=alice → Welcome, alice!
エクスプロイトリクエスト
/?name=!!javax.script.ScriptEngineManager []
脆弱な SnakeYAML は攻撃者が指定したクラスをインスタンス化し、アプリは "You've been pwned" ページを表示し、その後サーバーは強制終了されます(数秒後 — ページが先に配信されるためです)。リロードするとアプリは消えています — ngrok 経由では "endpoint offline" ページが表示されます。これはオブジェクトインジェクションのプリミティブであり、完全なエクスプロイトは(URLClassLoader を介して)それを連鎖させてリモートコードをロードして実行します。
.
├── pom.xml # 脆弱な依存関係を宣言
├── src/main/java/… # Spring Boot アプリ(HelloController、DataService)
├── .seal-actions.yml # オプションのローカル修正モードマッピング(脆弱 → 封印)
├── Jenkinsfile # Seal ステージを含む Jenkins(Groovy)パイプラインの例
└── .github/workflows/
├── build-and-run.yml # ビルド + ブラウザテスト用にアプリを公開
└── seal-security.yml # Seal の修復を実行し、アプリを起動
Seal は SaaS、Seal ホスト型です — 環境内には何もインストールされず、すべてのトラフィックは**アウトバウンド HTTPS(TCP 443 のみ)**です。修復を実行するために必要なもの:
| シークレット / 認証情報 | 用途 | 設定場所 |
|---|---|---|
これらは Settings → Secrets and variables → Actions(GitHub)または Manage Jenkins → Credentials(Jenkins)で設定してください。トークンをリポジトリにコミットしないでください。
アウトバウンド 443 でこれらの Seal ホストを許可リストに追加してください:
app.sealsecurity.io、authorization.sealsecurity.io、cli.sealsecurity.io、および封印された Maven アーティファクト用に maven.sealsecurity.io。CLI バイナリは github.com / objects.githubusercontent.com からダウンロードされます。
mvn clean package -DskipTests
java -jar target/java-example-1.0.0.jar # → http://localhost:8080
http://localhost:8080/?name=alice を開きます(動作します)。次に
http://localhost:8080/?name=!!javax.script.ScriptEngineManager [] を開きます — アプリは
"You've been pwned" を表示し、サーバーは数秒後に強制終了されます。
Seal CLI は、依存関係が解決された後、パッケージングの前に1つの追加ステップとして実行されます。解決された依存関係をスキャンし、脆弱なものを封印バージョンに書き換えます。リモート修正モード(ポリシーは Seal UI で中央管理)を使用します。
seal-community/cli-action を使用:
- uses: seal-community/cli-action@latest
with:
mode: fix
fix_mode: remote
token: ${{ secrets.SEAL_TOKEN }}
target: pom.xml # このエコシステムのマニフェスト
Actions → "Seal Security Remediation" → Run workflow で実行します。.github/workflows/seal-security.yml を参照してください。
依存関係の解決後、パッケージング前に追加される単一のステージです。Jenkinsfile を参照してください:
stage('Seal') {
steps {
sh '''
curl -fsSL https://github.com/seal-community/cli/releases/download/latest/seal-linux-amd64-latest -o seal
chmod +x seal
./seal fix --mode remote "$SEAL_MANIFEST" # SEAL_MANIFEST=pom.xml
'''
}
}
SEAL_TOKEN は seal-token Jenkins 認証情報から取得されます。SEAL_PROJECT には Seal プロジェクト ID を設定します。
seal fix 後、脆弱な依存関係は Seal の Maven レジストリの封印ビルドに解決されます — 同じ座標、セキュリティ修正はバックポート済みです:
封印バージョンとは、セキュリティ修正がバックポートされた同じアーティファクトです — ドロップイン置き換えであり、コード変更もメジャーバージョンアップグレードも不要です。
修復されたアプリに対してエクスプロイトを再実行します。封印された snakeyaml は悪意のあるグローバル型のインスタンス化を拒否するため、ペイロードはリモート JAR をロードできなくなり、リモートコード実行がブロックされます。
seal fix を特定のマニフェストに向けます — Maven の場合は pom.xml。マルチモジュールビルドの場合は、マニフェストごとに seal fix を1回実行します。これで統合は完了です — 1つのステージ、アウトバウンドのみ、アプリケーションコードの変更はありません。
| Seal トークン |
| Seal CLI の認証 |
GitHub Actions のシークレット SEAL_TOKEN / Jenkins の "Secret text" 認証情報 seal-token |
| ngrok トークン (オプション) | 実行中のアプリをブラウザテスト用に公開 | GitHub Actions のシークレット NGROK_TOKEN |
| 依存関係 | 変更前 | 変更後(封印) |
|---|
| org.yaml:snakeyaml | 1.33 | 1.33+sp1 |
| com.fasterxml.jackson.core:jackson-databind | 2.13.1 | 2.13.1+sp1 |
| org.apache.commons:commons-text | 1.9 | 1.9+sp1 |
| org.springframework:spring-core / spring-web | 5.3.26 | 5.3.26+sp1 |
| net.minidev:json-smart | 2.4.8 | 2.4.8+sp1 |
| org.apache.commons:commons-lang3 | 3.12.0 | 3.12.0+sp1 |
| org.springframework.boot:spring-boot | 2.7.18 | 2.7.18+sp1 |