[Bug] OceanBase sink JDBC URL sensitive parameters are never filtered (INLONG-11731 fix is incomplete): `autoDeserialize` passes through to Connector/J
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 65/100
Direzione di ricerca
The fix must be applied in OceanBaseSinkDTO.getFromRequest in inlong-manager/manager-pojo to call the sensitive-parameter filter, similar to MySQLSinkDTO. Then verify that OceanBaseLoadNode.tableOptions in inlong-sort/sort-common receives the filtered URL. Test by creating an OceanBase sink with autoDeserialize=true and ensuring the parameter is removed before reaching the JDBC connector.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
What happened
INLONG-11731 / PR #11732 hardened MySQLSensitiveUrlUtils (case-insensitive matching and the yeſ long-s variant) for the MySQL sink entry. However, the OceanBase sink entry never passes the JDBC URL through any sensitive-parameter filter at all, and the URL is forwarded verbatim to the Flink JDBC connector. A tenant user who creates/updates an OceanBase sink can therefore transport autoDeserialize=true (and other dangerous Connector/J parameters) end-to-end and trigger Java deserialization in the Sort runtime.
Root cause chain (all verified against released artifacts):
inlong-manager/manager-pojo/.../sink/oceanbase/OceanBaseSinkDTO.java
getFromRequest(...)never callsfilterSensitive(...)— although its
@apiNoteexplicitly says "filter sensitive params before saving". The raw
attacker-controlled URL is stored in the sink config.inlong-sort/sort-common/.../node/load/OceanBaseLoadNode.java
tableOptions()doesoptions.put("url", url)verbatim (line ~89).jdbc-inlongconnector (Flink 1.15/1.18)JdbcDynamicTableFactory
passes the URL to Connector/J without any runtime scrubbing
(JdbcUrlUtils.replaceInvalidUrlPropertyexists only in the 1.13 module,
and even that only replaces the exact stringautoDeserialize=true;
autoDeserialize=yessurvives it).- With
autoDeserialize=true, Connector/J auto-deserializes Java-serialized
BLOB values onResultSet.getObject(). If the Sort classpath contains a
usable gadget chain, this is RCE in the Flink TaskManager.
The Manager-side MySQL entry (MySQLSinkDTO.getFromRequest) does call
filterSensitive, so the OceanBase entry is the gap left by PR #11732 —
OceanBaseJdbcUtils.establishDatabaseConnection (Manager-side connectivity
check) filters, but that is not the path that feeds Sort.
What you expected to happen
OceanBase sink creation should apply the same sensitive-parameter filtering as
the MySQL sink does after INLONG-11731, i.e.
OceanBaseSinkDTO.getFromRequest(request, extParams)
should neutralize autoDeserialize / allowLoadLocalInfile / allowUrlInLocalInfile
/ allowLoadLocalInfileInPath (and ideally reject queryInterceptors /
statementInterceptors) before the config is saved — so that what reaches
OceanBaseLoadNode.tableOptions() and eventually Connector/J is incapable of
enabling auto-deserialization.
Current actual behaviour (verified): URL containing autoDeserialize=true
submitted via the OceanBase sink request passes unchanged through
OceanBaseSinkDTO.getFromRequest -> OceanBaseLoadNode.tableOptions() ->
Flink jdbc-inlong connector -> Connector/J, and deserialization is executed
during ResultSet.getObject().
How to reproduce
Minimal end-to-end reproduction using released InLong 2.2.0 artifacts and a
real MySQL server (Docker):
- Start MySQL:
docker run -d --name ob-poc -e MYSQL_ROOT_PASSWORD=root123 \
-e MYSQL_DATABASE=testdb -p 3307:3306 mysql:5.7
-
Prepare the "attacker-controlled" table: write one row whose BLOB column
contains a Java-serialized object of a class whosereadObject()has a
visible side effect (e.g., creates a marker file). Any real-world exploit
would use a public gadget chain (e.g., CommonsCollections) instead of the
marker class. -
Run the chain with the official released classes (manager-pojo 2.2.0,
sort-common 2.2.0, mysql-connector-j 8.0.33):
// 1) Manager entry: exactly what OceanBaseSinkDTO.getFromRequest does with
// an OceanBaseSinkRequest carrying the attacker URL.
OceanBaseSinkDTO dto = OceanBaseSinkDTO.getFromRequest(request, null);
System.out.println("after getFromRequest url = " + dto.getJdbcUrl());
// -> jdbc:mysql://127.0.0.1:3307/testdb?autoDeserialize=true (NOT filtered)
// 2) Sort layer: what OceanBaseLoadNode emits for the connector
Map<String, String> opts = new OceanBaseLoadNode(dto.getJdbcUrl(), ...).tableOptions();
System.out.println("tableOptions url = " + opts.get("url"));
// -> jdbc:mysql://127.0.0.1:3307/testdb?autoDeserialize=true (verbatim)
// 3) Runtime: what the jdbc-inlong connector ultimately does
Connection conn = DriverManager.getConnection(opts.get("url"), "root", "root123");
ResultSet rs = conn.createStatement().executeQuery("SELECT blob_col FROM loot").get(1), ...
Object o = rs.getObject(1); // triggers deserialization
// -> marker file PWNED.txt created by the serialized object's readObject()
Negative control: the identical query with autoDeserialize absent returns
byte[] instead and creates no marker file — the behaviour difference is
caused solely by this one parameter.
Also reproducible: with the 1.13 JdbcUrlUtils.replaceInvalidUrlProperty,
jdbc:mysql://...?autoDeserialize=yes is NOT neutralized (only the exact
string autoDeserialize=true is replaced), and Connector/J parses
autoDeserialize=yes as true.
Environment
- OS: Linux x86_64
- JDK: OpenJDK 1.8.0_452
- MySQL Server: 5.7 (Docker
mysql:5.7) - Connector/J: com.mysql:mysql-connector-j 8.0.33 (also verified with mysql:mysql-connector-java 8.0.28)
- Apache Spark/Flink runtime: not required – the invocation was exercised with the released InLong jars directly
InLong version
master
InLong Component
InLong Manager, InLong Sort
Are you willing to submit PR?
- Yes, I am willing to submit a PR!
Code of Conduct
- I agree to follow this project's Code of Conduct
- Lingua principale
- Java
- Stelle
- 1.5k
- Fork
- 570
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di apache/inlong
-
[Improve][SDK] Support configuring request timeout in the DataProxy Go SDK discovererForse già presa @yfsn666 l’ha presa 62 giorni fa. Apertastage/stale type/improve
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
-
[Improve][SDK] Fix potential goroutine leak on close in the DataProxy Go SDK by closing connPool before netClientForse già presa @yfsn666 l’ha presa 62 giorni fa. Apertastage/stale type/improve
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
-
[Improve][SDK] Update message metrics when no available worker in the DataProxy Go SDKForse già presa @yfsn666 l’ha presa 62 giorni fa. Apertastage/stale type/improve
Difficoltà 3/5 1-2 giorni Idoneità per principianti 55/100
-
[Improve][SDK] Avoid calling endpoint update handlers while holding the lock in the Dataproxy Go SDK discoverersForse già presa @yfsn666 l’ha presa 62 giorni fa. Apertastage/stale type/improve
Difficoltà 3/5 1-2 giorni Idoneità per principianti 55/100
-
[Improve][SDK] Fix panic on sending to a closed channel during shutdown in the DataProxy Go SDKForse già presa @yfsn666 l’ha presa 62 giorni fa. Apertastage/stale type/improve
Difficoltà 3/5 1-2 giorni Idoneità per principianti 57/100
Tutte le issue di apache/inlong
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
oracle/graalvm-reachability-metadata#11472 ·
I maintainer di solito rispondono entro 1 giorno
-
OkHttp versions 5.4.0+ no longer include baseline-prof.txtForse già presa Una pull request collegata a questa issue è aperta o già unita. Apertabug
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 83/100
lysine-dev/okhttp#9828 ·
I maintainer di solito rispondono entro 1 giorno
-
status: waiting-for-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
spring-projects/spring-ai#7269 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 89/100
objectionary/hone-maven-plugin#1353 ·
I maintainer di solito rispondono entro 9 giorni
-
ClassNotFoundException: io.netty.channel.kqueue.KQueueEventLoop stack trace printed during native build on main (Netty 4.2 removed the class)Forse già presa @gastaldi l’ha presa oggi. Apertaarea/netty kind/bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
quarkusio/quarkus#57939 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno