Apache Druid JNDI注入漏洞分析
2023-4-24 17:37:49 Author: JDArmy(查看原文) 阅读量:28 收藏

Apache Druid JNDI注入漏洞分析

影响版本:全版本

环境搭建

下载环境和源码https://archive.apache.org/dist/druid/0.19.0/

配置远程调试

cd ./conf/druid/single-server/micro-quickstart/coordinator-overlord

编辑jvm.config,添加以下内容

jdk8

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

jdk11

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005

启动环境

./bin/start-micro-quickstart

因为默认是jdk8,如果你的环境是jdk11遇到报错,执行以下命令再重新启动

export DRUID_SKIP_JAVA_CHECK=1

搭建成功

IDEA配置

到此环境搭配、远程调试配置完毕可以开始漏洞分析了。

漏洞分析

先根据jackson反序列化json字符串,看看ioConifg是哪个类。consumerProperties是什么类型字段,发现是个Map集合(String--->Object),也就是说我们可以添加任何我们想添加的内容。

但是为什么需要添加security.protocolsasl.mechanismsasl.jaas.config这几个字段呢?我们一步步来看

先是在org.apache.druid.indexing.kafka.KafkaSamplerSpec->createRecordSupplier方法中提取了传入的ConsumerProperties内容。

随后在org.apache.kafka.clients.ClientUtils->createChannelBuilder方法中提取出了security.protocolsasl.mechanism两个字段的值,因为后面链条的走向会因为security.protocol值的变化而改变。所以poc中需要填入这两个字段。那为什么需要"security.protocol":"SASL_SSL"我们接着看

"security.protocol":"SASL_SSL"时会进入分支SASL_SSL而这个分支刚好没写break,顺势进入了SASL_PLAINTEXT,走进我们想要的JassContext.loadClientContext方法。当然如果你这么赋值"security.protocol":"SASL_PLAINTEXT"也是可以的哈哈,当我没说过。

JassContext.loadClientContext做的就是提取sasl.jaas.config并转换成Password类型,关键是load方法,这里会把提取出来的字符串进行分割最后转换成JassConfig类型,存入jaasContexts

接着跟进org.apache.kafka.common.network.SaslChannelBuilder->configure方法迭代jassContexts提取传入LoginManager.acquireLoginManager

继续跟进

new LoginContext的时候为moduleStack赋值,后面触发漏洞方法就是从moduleStack中去迭代获取。

最后就是触发java原生lookup

贴一下调用栈

attemptAuthentication:509, JndiLoginModule (com.sun.security.auth.module)
login:279, JndiLoginModule (com.sun.security.auth.module)
invoke:747, LoginContext (javax.security.auth.login)
run:672, LoginContext$4 (javax.security.auth.login)
run:670, LoginContext$4 (javax.security.auth.login)
doPrivileged:-1, AccessController (java.security)
invokePriv:670, LoginContext (javax.security.auth.login)
login:581, LoginContext (javax.security.auth.login)
login:60, AbstractLogin (org.apache.kafka.common.security.authenticator)
<init>:62, LoginManager (org.apache.kafka.common.security.authenticator)
acquireLoginManager:105, LoginManager (org.apache.kafka.common.security.authenticator)
configure:158, SaslChannelBuilder (org.apache.kafka.common.network)
create:157, ChannelBuilders (org.apache.kafka.common.network)
clientChannelBuilder:73, ChannelBuilders (org.apache.kafka.common.network)
createChannelBuilder:105, ClientUtils (org.apache.kafka.clients)
<init>:743, KafkaConsumer (org.apache.kafka.clients.consumer)
<init>:666, KafkaConsumer (org.apache.kafka.clients.consumer)
getKafkaConsumer:248, KafkaRecordSupplier (org.apache.druid.indexing.kafka)
<init>:63, KafkaRecordSupplier (org.apache.druid.indexing.kafka)
createRecordSupplier:66, KafkaSamplerSpec (org.apache.druid.indexing.kafka)
createRecordSupplier:36, KafkaSamplerSpec (org.apache.druid.indexing.kafka)
sample:97, SeekableStreamSamplerSpec (org.apache.druid.indexing.seekablestream)
post:41, SamplerResource (org.apache.druid.indexing.overlord.sampler)
invoke:-1, GeneratedMethodAccessor28 (jdk.internal.reflect)
invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
invoke:566, Method (java.lang.reflect)
invoke:60, JavaMethodInvokerFactory$1 (com.sun.jersey.spi.container)
_dispatch:185, AbstractResourceMethodDispatchProvider$TypeOutInvoker (com.sun.jersey.server.impl.model.method.dispatch)
dispatch:75, ResourceJavaMethodDispatcher (com.sun.jersey.server.impl.model.method.dispatch)
accept:302, HttpMethodRule (com.sun.jersey.server.impl.uri.rules)
accept:108, ResourceClassRule (com.sun.jersey.server.impl.uri.rules)
accept:147, RightHandPathRule (com.sun.jersey.server.impl.uri.rules)
accept:84, RootResourceClassesRule (com.sun.jersey.server.impl.uri.rules)
_handleRequest:1542, WebApplicationImpl (com.sun.jersey.server.impl.application)
_handleRequest:1473, WebApplicationImpl (com.sun.jersey.server.impl.application)
handleRequest:1419, WebApplicationImpl (com.sun.jersey.server.impl.application)
handleRequest:1409, WebApplicationImpl (com.sun.jersey.server.impl.application)
service:409, WebComponent (com.sun.jersey.spi.container.servlet)
service:558, ServletContainer (com.sun.jersey.spi.container.servlet)
service:733, ServletContainer (com.sun.jersey.spi.container.servlet)
service:790, HttpServlet (javax.servlet.http)
doServiceImpl:286, ServletDefinition (com.google.inject.servlet)
doService:276, ServletDefinition (com.google.inject.servlet)
service:181, ServletDefinition (com.google.inject.servlet)
service:91, ManagedServletPipeline (com.google.inject.servlet)
doFilter:85, FilterChainInvocation (com.google.inject.servlet)
dispatch:120, ManagedFilterPipeline (com.google.inject.servlet)
doFilter:135, GuiceFilter (com.google.inject.servlet)
doFilter:1642, ServletHandler$CachedChain (org.eclipse.jetty.servlet)
doFilter:73, RedirectFilter (org.apache.druid.server.http)
doFilter:1642, ServletHandler$CachedChain (org.eclipse.jetty.servlet)
doFilter:82, PreResponseAuthorizationCheckFilter (org.apache.druid.server.security)
doFilter:1642, ServletHandler$CachedChain (org.eclipse.jetty.servlet)
doFilter:78, AllowHttpMethodsResourceFilter (org.apache.druid.server.security)
doFilter:1642, ServletHandler$CachedChain (org.eclipse.jetty.servlet)
doFilter:75, AllowOptionsResourceFilter (org.apache.druid.server.security)
doFilter:1642, ServletHandler$CachedChain (org.eclipse.jetty.servlet)
doFilter:84, AllowAllAuthenticator$1 (org.apache.druid.server.security)
doFilter:59, AuthenticationWrappingFilter (org.apache.druid.server.security)
doFilter:1642, ServletHandler$CachedChain (org.eclipse.jetty.servlet)
doFilter:86, SecuritySanityCheckFilter (org.apache.druid.server.security)
doFilter:1642, ServletHandler$CachedChain (org.eclipse.jetty.servlet)
doHandle:533, ServletHandler (org.eclipse.jetty.servlet)
nextHandle:255, ScopedHandler (org.eclipse.jetty.server.handler)
doHandle:1595, SessionHandler (org.eclipse.jetty.server.session)
nextHandle:255, ScopedHandler (org.eclipse.jetty.server.handler)
doHandle:1340, ContextHandler (org.eclipse.jetty.server.handler)
nextScope:203, ScopedHandler (org.eclipse.jetty.server.handler)
doScope:473, ServletHandler (org.eclipse.jetty.servlet)
doScope:1564, SessionHandler (org.eclipse.jetty.server.session)
nextScope:201, ScopedHandler (org.eclipse.jetty.server.handler)
doScope:1242, ContextHandler (org.eclipse.jetty.server.handler)
handle:144, ScopedHandler (org.eclipse.jetty.server.handler)
handle:740, GzipHandler (org.eclipse.jetty.server.handler.gzip)
handle:61, HandlerList (org.eclipse.jetty.server.handler)
handle:132, HandlerWrapper (org.eclipse.jetty.server.handler)
handle:503, Server (org.eclipse.jetty.server)
handle:364, HttpChannel (org.eclipse.jetty.server)
onFillable:260, HttpConnection (org.eclipse.jetty.server)
succeeded:305, AbstractConnection$ReadCallback (org.eclipse.jetty.io)
fillable:103, FillInterest (org.eclipse.jetty.io)
run:118, ChannelEndPoint$2 (org.eclipse.jetty.io)
runTask:333, EatWhatYouKill (org.eclipse.jetty.util.thread.strategy)
doProduce:310, EatWhatYouKill (org.eclipse.jetty.util.thread.strategy)
tryProduce:168, EatWhatYouKill (org.eclipse.jetty.util.thread.strategy)
run:126, EatWhatYouKill (org.eclipse.jetty.util.thread.strategy)
run:366, ReservedThreadExecutor$ReservedThread (org.eclipse.jetty.util.thread)
runJob:765, QueuedThreadPool (org.eclipse.jetty.util.thread)
run:683, QueuedThreadPool$2 (org.eclipse.jetty.util.thread)
run:834, Thread (java.lang)

文章来源: http://mp.weixin.qq.com/s?__biz=Mzk0ODI2NjUzMQ==&mid=2247484153&idx=1&sn=5694d51a5360e84e19322d18a60e42e6&chksm=c36b71b5f41cf8a3ac1cbc45924570c41ef6e7f232468f9a300b20b742b0fa38c46bed38e075#rd
如有侵权请联系:admin#unsafe.sh