An Introduction to Apache Dubbo and CVE 2019-17564 Analysis

Tram Ho

What is RPC?

Remote Procedure Calls (RPC) are a powerful technique for building distributed applications. It is based on extending the usual local procedure invocation so that the called procedure does not need to exist in the same address space as the calling procedure. The two processes can be on the same system or they can be on different systems with the network connecting them.

  1. The calling environment is paused, procedure parameters are passed over the network to the environment where the procedure is executed and the procedure is executed there.
  2. When the procedure finishes and produces its result, its result is passed back to the calling environment, where execution continues as if returning from a regular procedure call.

RPC can be seen as a normal request-respone protocol, however it is used for server-server communication rather than client-server. This is very important because in a distributed system, the application code is on more than one server server. The most common example is the Microservices architecture.

This means: a request on the client side may need many services running on these servers to synthesize information before responding to the client. The communication between servers will now be a problem that before all services running on one server are fine, because the local call should not be concerned. Exactly then, when a server wants to “talk” to another server, it will need to encode data (JSON, XML), the receiver also has to do the opposite job of decode data to understand what the other guy said to me. must re-encode. This consumes a lot of processing resources (CPU) that should only be done at the beginning and end (the receiver and the last return).

Introducing apache dubbo

Dubbo is an open source Alibaba RPC and microservice framework.

It enhances service administration and makes traditional monolithic applications smoothly refactored into a scalable distributed architecture.

In this article, I’ll take a look at Dubbo and its most important features.

Architecture

Dubbo includes several ingredients:

  1. Provider – Provider – the provider will create its service for registration
  2. Container – Container – where the service is created, loaded, and run
  3. Consumer – the person requesting the remote services; the consumer will subscribe to the required service in the registry
  4. Registry – The Registry – where the service will be registered
  5. Monitor – records statistics for services, for example, the frequency of service calls over a given period of time

The connection between Provider , Consumer and Registry is continuous, so whenever a Provider has problems, the Registry can detect the error and notify Consumer .

Registry and Monitor are optional. Consumer can connect directly with Provider , but the stability of the whole system will be affected.

The activities of dubbo are described as follows:

  1. Container is responsible for initializing, loading and running Provider .
  2. Provider registers its services to the Register during the initialization.
  3. Consumer registers the services they need from Register when it starts.
  4. Register returns Provider list to Consumer and when a change occurs, Register will push the changed data to Consumer .
  5. Consumer selects one of the Provider based on the soft load balancing algorithm, then makes the call, automatically chooses another Provider when an error occurs.
  6. Both Consumer and Provider count service calls and usage time in memory and send statistics to Monitor every minute.

Dubbo has the following features: Connectivity, Powerful, Scalable and Scalable.

List of java deserialization vulnerabilities related to apache dubbo:

  • CVE-2020-11995
  • CVE-2020-1948
  • CVE-2019-17564

CVE 2019-17564 Analysis

Apache Dubbo supports many protocols like dubbo , hessian , http ….. All are listed on https://dubbo.apache.org/en/docs/v2.7/user/references/protocol/ . By default, the Dubbo RPC Framework uses the dubbo protocol.

CVE-2019-17564 is a deserialization vulnerability that occurs when the Apache Dubbo HTTP protocol is used, An attacker can send a POST request with a malicious object to a URL of the Apache Dubbo HTTP service, which will lead to remote code execution.

Affected versions

  • 2.7.0 <= Apache Dubbo <= 2.7.4
  • 2.6.0 <= Apache Dubbo <= 2.6.7
  • Apache Dubbo = 2.5.x

Environment reconstruction

For the convenience of setting up the environment, visit the dubbo-Sample github project homepage and download dubbo-sample (https://github.com/apache/dubbo-samples)

After downloading the source code, select dubbo-sample-http and open it as a project in Intelij

After the project has finished loading. We will fix dubbo version 2.7.3 so that it can be exploited. Note that adding <version>2.7.3</version> on line 81 will make your changes successful

Next we will need a zookeeper for the dubbo to connect to. Zookeeper is a centralized service (a server) for maintaining configuration information, naming, providing distributed synchronization, providing group services. In other words, Zookeeper is a distributed coordination service for distributed applications. The client connects to a ZooKeeper server (a single node). The client maintains a TCP connection through sending and receiving requests, responses, and listening for events … If the server dies, the client will be connected to another server. You can download the zookeeper here: https://zookeeper.apache.org/releases.html .

After downloading the zookeeper you launch it to zkServer.bat . Note that before running, you create a zoo.cfg file in the conf directory with the content copied from the zoo_sample.cfg file:

If the display like this is successful already.

Analysis and debugging.

Do not run the HttpProvider class. Realizing the provider registered a service with zookeeper http://172.22.224.1:8089/org.apache.dubbo.samples.http.api.DemoService?anyhost=true&application=http-provider&bean.name=org.apache.dubbo.samples.http.api.DemoService&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.samples.http.api.DemoService&methods=sayHello&pid=8700&register=true&release=2.7.3&server=tomcat&side=provider&timestamp=1618451446458

Since this is an Http service, we can completely catch requests with burpsuite to modify. Create a request to the above service, and capture it with burpsuite for easy modification

This request will go through the method org.apache.dubbo.remoting.http.servlet.DispatcherServlet.service because the DispatcherServlet class inherits the javax.servlet.http.HttpServlet class, which handles all http requests sent to the server. Set breakpoint at line 43.

An easy way to see the flow of the program is to look at the stack trace on the left corner of the Intelij screen. With the top of the satck is where we are standing.

Press F7 to jump to the next method which is: /org/apache/dubbo/rpc/protocol/http/HttpProtocol.handle

Keep an eye on line 211. This code will check what kind of method the request we send up. If it is different from POST , 500 will always be returned without processing. So to be able to go to line 216, we need to edit the request to a POST request and try again. After repeating the above steps, we set the breakpoint at line 216 and press F7 to jump to the next handler method, org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter.handleRequest

The job of this method is to read a remote invocation from the request, execute it, and write the result of the remote call into the response. Notice the readRemoteInvocation method is responsible for reading our request. Jump to that method to see more

We see after jumping into the above method it continues to call a method of the same name to read the InputStream in the request. Pay attention to param request.getInputStream() . Here, for some people who have studied java deserialization here will immediately realize the problem lies in this place already. It is reading any stream that the user enters in the POST request. Notice on line 119 the program recreated the ObjectInputStream from the stream we sent it and passed the doReadRemoteInvocation method. Jump into this method to continue reading.

So far, the program executes readObject (). From here, we have endpoind to trigger the java deserialization vulnerability. Next is just a matter of finding a chain to be able to continue mining. This issue depends on the jar packages in the project and on the actual situation. Here for simplicity I will add commons-collectons:3.2 to demo this vulnerability.

After reloading the program. I use a nice burp suite extension called Deserialization Scanne . It can generate payloads and send them directly to the server. Here I use gadget chain CommonsCollection 5 offline.

And here is my result.

Refer

https://www.geeksforgeeks.org/remote-procedure-call-rpc-in-operating-system/ https://www.baeldung.com/dubbo https://dubbo.apache.org/en/docs/v2 .7 / user / preface / architecture / https://y4er.com/post/apache-dubbo-cve-2019-17564/

Share the news now

Source : Viblo