[SECURITY] Apache Security report one issue - in Apache CarbonData 2.3.2, unauthenticated Java deserialization RCE on the Distributed Index Server IPC endpoint (IndexInputFormat filter, no ObjectInputFilter)
- Dominant language
- Scala
- Stars
- 1.5k
- Forks
- 694
- PR merge metrics
- No merged PRs in 30d
Description
The issue detail info as below :
Summary:
The Index Server is a Hadoop IPC service whose RPC methods take an IndexInputFormat argument:
// integration/spark/.../indexserver/IndexServer.scala
@ProtocolInfo(protocolName = "org.apache.carbondata.indexserver.ServerInterface", ...)
@KerberosInfo(...)
trait ServerInterface {
def getSplits(request: IndexInputFormat): ExtendedBlockletWrapperContainer
def getCount(request: IndexInputFormat): LongWritable
def getPrunedSegments(request: IndexInputFormat): SegmentWrapperContainer
}
val server = new RPC.Builder(conf).setInstance(this).setProtocol(classOf[ServerInterface]).build
IndexInputFormat is a Hadoop Writable, so IPC reconstructs the argument via readFields(DataInput), reading an attacker-controlled blob straight off the wire and deserializing it:
// core/.../index/IndexInputFormat.java:319-324 (readFields)
byte[] filterResolverBytes = new byte[in.readInt()];
in.readFully(filterResolverBytes, 0, filterResolverBytes.length);
this.filterResolverIntf = (FilterResolverIntf) ObjectSerializationUtil
.convertStringToObject(new String(filterResolverBytes, Charset.defaultCharset()));
// core/.../util/ObjectSerializationUtil.java:84-99 (the sink, no filter)
ois = new ClassLoaderObjectInputStream(Thread.currentThread().getContextClassLoader(), gis);
return ois.readObject(); // no ObjectInputFilter / allow-list
The cast to FilterResolverIntf happens after readObject() returns, so a gadget chain fires during deserialization. Any client that can reach the Index Server IPC port can send getSplits() with a crafted IndexInputFormat and trigger deserialization of arbitrary classes on the server JVM.
Authentication:
On a non-Kerberized cluster (SIMPLE Hadoop auth, the default) the endpoint is unauthenticated: the protocol is @KerberosInfo and the server registers an IndexServerPolicyProvider ACL via refreshServiceAcl, but that ACL is only enforced when hadoop.security.authorization=true, and in SIMPLE auth the remote identity (Server.getRemoteUser) is client-asserted/spoofable. Kerberized clusters with the ACL configured require valid Kerberos (an authenticated insider could still reach the sink). The Index Server is an opt-in feature (carbon.enable.index.server defaults to false).
Impact:
Remote Java-deserialization code execution on the Index Server JVM (runs in the Spark driver of the Index Cache Server, typically with cluster/service privileges). CarbonData runs on Spark + Hadoop, so deserialization gadget libraries are typically on the classpath, making this arbitrary command execution; without a code-exec gadget it is still a DoS / object-injection primitive. (CWE-502 Deserialization of Untrusted Data; CWE-306 in the default non-Kerberized deployment.)
Proof of concept:
A green harness that loads the real carbondata-core-2.3.2.jar and calls the real ObjectSerializationUtil.convertStringToObject(...) on an attacker-crafted string, an arbitrary class is instantiated and its readObject() executes, proving the sink has no ObjectInputFilter. Output: >>> GREEN: EvilGreen.readObject() executed during REAL CarbonData deser sink >>> CONFIRMED: unfiltered readObject on the real CarbonData sink executed attacker code.
Confirmation status:
The unfiltered-deserialization sink is executed live against the real release jar; the wire->sink reachability (IPC getSplits -> IndexInputFormat.readFields -> convertStringToObject) is traced in source. Not stood up end-to-end against a live Index Server; the live check is to start an Index Server on a SIMPLE-auth cluster and send getSplits with a ysoserial payload in filterResolverBytes.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with integration/spark/.../indexserver/IndexServer.scala, core/.../index/IndexInputFormat.java, and core/.../util/ObjectSerializationUtil.java; trace getSplits through readFields to convertStringToObject. Determine an approved mitigation for untrusted deserialization and SIMPLE-auth access, then verify the sink no longer accepts attacker-controlled objects and cover the path with a regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- hadoop, java, scala, spark
- Domain
- distributed-systems, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100