影响版本:全版本
下载环境和源码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.protocol
、sasl.mechanism
、sasl.jaas.config
这几个字段呢?我们一步步来看
先是在org.apache.druid.indexing.kafka.KafkaSamplerSpec->createRecordSupplier
方法中提取了传入的ConsumerProperties内容。
随后在org.apache.kafka.clients.ClientUtils->createChannelBuilder
方法中提取出了security.protocol
和sasl.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)