chenliang613 opened a new issue, #4399:
URL: https://github.com/apache/carbondata/issues/4399
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.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]