Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DecodeableRpcInvocation增加入参类型校验 #6374

Merged
merged 4 commits into from
Jul 1, 2020

Conversation

aquariuspj
Copy link
Contributor

目的

加固 关于CVE-2020-1948 的问题修复。

问题

通过简单的修改CVE-2020-1948的POC示例,我在dubbo-2.7.7中再次复现了该问题。

  1. 使用 https://github.com/apache/dubbo-spring-boot-project 最新的2.7.7的TAG分支。
  2. 其他poc内容参照:https://blog.csdn.net/caiqiiqi/article/details/106934770,但修改其中POC的部分代码:
    resp = client.send_request_and_return_response(
    service_name='org.apache.dubbo.spring.boot.demo.consumer.DemoService',
    method_name='rce',
    args=[toStringBean])

修改为

    resp = client.send_request_and_return_response(
    service_name='org.apache.dubbo.spring.boot.sample.consumer.DemoService',
    method_name='$invoke',
    service_version='1.0.0',
    args=[toStringBean])

注入的恶意代码ExploitMac.java依然会被执行。

提交内容

  1. DecodeableRpcInvocation解码时,对$invoke、$invokeAsync、$echo等特殊方法进行参数描述的校验,防止外部输入不合法的参数类型。

@haiyang1985
Copy link
Member

这个修复好像一点都拦不住恶意代码,看下面这个例子,藏在types和objects里的恶意代码,你根本识别不了,也无法判断到底是不是恶意代码。

String[] types = new String[]{"com.xxx.rome"};
Object[] objects = new Object[]{new RomeObject()};
service.$invoke("$invoke", types, objects);

@aquariuspj aquariuspj closed this Jun 30, 2020
@aquariuspj
Copy link
Contributor Author

这个修复好像一点都拦不住恶意代码,看下面这个例子,藏在types和objects里的恶意代码,你根本识别不了,也无法判断到底是不是恶意代码。

String[] types = new String[]{"com.xxx.rome"};
Object[] objects = new Object[]{new RomeObject()};
service.$invoke("$invoke", types, objects);

抱歉...github这块操作我还不太熟悉..不小心点了很多奇怪的操作。

  1. 假设service.$invoke(String, String[], Object[])方法的声明确实存在,那么由于入参类型正确,因此恶意对象RemoObject的反序列化过程也一定会是正确的,此时也不会触发toString这个注入点。
  2. 如果入参类型全都正确,那么就应该交给应用层对入参进行额外校验来保证调用的安全性。。

@aquariuspj aquariuspj reopened this Jun 30, 2020
@chickenlj
Copy link
Contributor

LGTM.

@chickenlj chickenlj added this to the 2.7.8 milestone Jun 30, 2020
@chickenlj
Copy link
Contributor

@aquariuspj Thanks for the enhancement. Next time when discussing a vulnerability issue, please send an email to security@dubbo.apache.org.

@haiyang1985
Copy link
Member

这个修复好像一点都拦不住恶意代码,看下面这个例子,藏在types和objects里的恶意代码,你根本识别不了,也无法判断到底是不是恶意代码。

String[] types = new String[]{"com.xxx.rome"};
Object[] objects = new Object[]{new RomeObject()};
service.$invoke("$invoke", types, objects);

抱歉...github这块操作我还不太熟悉..不小心点了很多奇怪的操作。

  1. 假设service.$invoke(String, String[], Object[])方法的声明确实存在,那么由于入参类型正确,因此恶意对象RemoObject的反序列化过程也一定会是正确的,此时也不会触发toString这个注入点。
  2. 如果入参类型全都正确,那么就应该交给应用层对入参进行额外校验来保证调用的安全性。。

你的规则应该只能挡住调用$invoke的入参也是错误的情况吧,只要参数是符合String,String[],Object[],即使包含了恶意代码,也防不住的吧?

  1. 如果请求的$invoke的入参是String,String[],Object[],而且objects包含了RomeObject恶意代码,这个请求的desc还是会符合Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;规则的。
  2. 参考下现在的反序列化过程,因为pts的length是3,也就会执行3次in.readObject(),其中就包括in.readObject(RemoObject),导致恶意代码被反序列化,只要恶意代码被反序列化了,不是就有可能会触发toString的注入点嘛。
args = new Object[pts.length];
for (int i = 0; i < args.length; i++) {
    try {
        args[i] = in.readObject(pts[i]);
    } catch (Exception e) {
        if (log.isWarnEnabled()) {
            log.warn("Decode argument failed: " + e.getMessage(), e);
        }
    }
}

@aquariuspj
Copy link
Contributor Author

aquariuspj commented Jun 30, 2020

这个修复好像一点都拦不住恶意代码,看下面这个例子,藏在types和objects里的恶意代码,你根本识别不了,也无法判断到底是不是恶意代码。

String[] types = new String[]{"com.xxx.rome"};
Object[] objects = new Object[]{new RomeObject()};
service.$invoke("$invoke", types, objects);

抱歉...github这块操作我还不太熟悉..不小心点了很多奇怪的操作。

  1. 假设service.$invoke(String, String[], Object[])方法的声明确实存在,那么由于入参类型正确,因此恶意对象RemoObject的反序列化过程也一定会是正确的,此时也不会触发toString这个注入点。
  2. 如果入参类型全都正确,那么就应该交给应用层对入参进行额外校验来保证调用的安全性。。

你的规则应该只能挡住调用$invoke的入参也是错误的情况吧,只要参数是符合String,String[],Object[],即使包含了恶意代码,也防不住的吧?

  1. 如果请求的$invoke的入参是String,String[],Object[],而且objects包含了RomeObject恶意代码,这个请求的desc还是会符合Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;规则的。
  2. 参考下现在的反序列化过程,因为pts的length是3,也就会执行3次in.readObject(),其中就包括in.readObject(RemoObject),导致恶意代码被反序列化,只要恶意代码被反序列化了,不是就有可能会触发toString的注入点嘛。
args = new Object[pts.length];
for (int i = 0; i < args.length; i++) {
    try {
        args[i] = in.readObject(pts[i]);
    } catch (Exception e) {
        if (log.isWarnEnabled()) {
            log.warn("Decode argument failed: " + e.getMessage(), e);
        }
    }
}

只要参数是符合String,String[],Object[],即使包含了恶意代码,也防不住的吧?

是的,入参类型正确,反序列化一定会被执行。
不过在方法调用入参完全符合接口声明的情况下,现有的逻辑不会执行到DubboProtocol中抛出异常时的toString注入点。

  1. 现有的反序列化过程我觉得其实是没问题的,反序列化只是还原对象本身的信息,它也无法校验对象所携带的信息是否是恶意的。
  2. DubboProtocol中抛出异常那部分逻辑如何修改我觉得可能还需要再做一些讨论,不过在那之前先对入参类型进行校验应该是一个比较好的选择。

@haiyang1985
Copy link
Member

haiyang1985 commented Jul 1, 2020

这个修复好像一点都拦不住恶意代码,看下面这个例子,藏在types和objects里的恶意代码,你根本识别不了,也无法判断到底是不是恶意代码。

String[] types = new String[]{"com.xxx.rome"};
Object[] objects = new Object[]{new RomeObject()};
service.$invoke("$invoke", types, objects);

抱歉...github这块操作我还不太熟悉..不小心点了很多奇怪的操作。

  1. 假设service.$invoke(String, String[], Object[])方法的声明确实存在,那么由于入参类型正确,因此恶意对象RemoObject的反序列化过程也一定会是正确的,此时也不会触发toString这个注入点。
  2. 如果入参类型全都正确,那么就应该交给应用层对入参进行额外校验来保证调用的安全性。。

你的规则应该只能挡住调用$invoke的入参也是错误的情况吧,只要参数是符合String,String[],Object[],即使包含了恶意代码,也防不住的吧?

  1. 如果请求的$invoke的入参是String,String[],Object[],而且objects包含了RomeObject恶意代码,这个请求的desc还是会符合Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;规则的。
  2. 参考下现在的反序列化过程,因为pts的length是3,也就会执行3次in.readObject(),其中就包括in.readObject(RemoObject),导致恶意代码被反序列化,只要恶意代码被反序列化了,不是就有可能会触发toString的注入点嘛。
args = new Object[pts.length];
for (int i = 0; i < args.length; i++) {
    try {
        args[i] = in.readObject(pts[i]);
    } catch (Exception e) {
        if (log.isWarnEnabled()) {
            log.warn("Decode argument failed: " + e.getMessage(), e);
        }
    }
}

只要参数是符合String,String[],Object[],即使包含了恶意代码,也防不住的吧?

是的,入参类型正确,反序列化一定会被执行。
不过在方法调用入参完全符合接口声明的情况下,现有的逻辑不会执行到DubboProtocol中抛出异常时的toString注入点。

  1. 现有的反序列化过程我觉得其实是没问题的,反序列化只是还原对象本身的信息,它也无法校验对象所携带的信息是否是恶意的。
  2. DubboProtocol中抛出异常那部分逻辑如何修改我觉得可能还需要再做一些讨论,不过在那之前先对入参类型进行校验应该是一个比较好的选择。

没太理解,要么加个钉钉详聊一下?钉钉:haiyang198542

@chickenlj chickenlj merged commit 5ad186f into apache:master Jul 1, 2020
mercyblitz added a commit that referenced this pull request Jul 2, 2020
* Polish #6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish #6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish #6171 : [Feature] Introducing the composite implementation of MetadataService

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989ca.

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989ca.

* Revert the MetadataReport

* Polish #6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event

* Polish #6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish #6310 : Refactoring MetadataReport's methods

* Polish #6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish #6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish #6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure

Deprecated List :

- NacosMetadataReport
- ZookeeperMetadataReport

* Polish #6315 : Refactoring by TreePathDynamicConfiguration

* Polish #6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration

* Polish #6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory

* Polish #6315 : Bugfix

* Polish #6315 : Bugfix

* Polish #6315 : Correct words

* sync wait netty server to finish shutdown (#6281)

* Polish #6333 : [Refactor] Using mandatory implementation of Service Instance registration instead of the event

* maybe we can remove null judge in this case (#6321)

* update

* update

* Polish #6336 : [Refactor] org.apache.dubbo.metadata.ServiceNameMapping

* Polish #6170 : [Feature] Introducing the externalized configuration for ServiceNameMapping

* Polish #6342 : [Enhancement] Introducing the composite ServiceNameMapping

* Refactor

* fix method name typo in JValidator.java (#6344)

* [Dubbo-6340]fix application cannot exit when use consul registry (#6341)

* fix application cannot exit when use consul registry

* make consul registry suppor ACL (#6313)

* make consul registry suppor ACL

* Polish #6172 : [Feature] Adding the "services" attribute methods into @DubboReference

* Polish #6173 : [Feature] Adding the "services" attribute into <dubbo:reference> element

* Polish #6346 : [Issue] Merging all subscribied URLs from the multiple services

* Polish #6346 : [Issue] Merging all subscribied URLs from the multiple services

* fix publish null value when use consul config center (#6351)

* fix publish null value when use consul config center

* Polish #6252

* Polish #6356 & #6171

* Polish #6356 & #6171

* Polish #6224 : Filter chain was not invoked with local calls since v2.7.6

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish #6322 : Adding META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter

* fix the priority of ListenableRouter were not effective (#6148)

fixes #4822

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* when the url is generic, the log level should be info (#6363)

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* fix NPE when check=false is set and provider is empty. (#6376)

fixes #6228

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* fix #6306.  support TypeBuilder sort (#6365)

* fix #6306. support TypeBuilder sort

* fix #6306. support TypeBuilder sort

* fix #6306. support TypeBuilder sort

* remove unused import

* add license for test file

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* enhance ClusterInvoker & ExtensionLoader (#6343)

- Introduce ClusterInvoker to better support multiple registries subscription
- Wrapper sort and enable/disable
- some small fixes

* Polish #6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Fixed the test-cases

* Enhancement, support Map auto recognize in PojoUtils (#6106)

Fix #5939

* Polish #6389 : [Issue] Resolving the issues with ConsulServiceDiscovery

* fix typo in CommonConstants (#6373)

* Fix export provider error, change to catch throwable, handle NoClassDefFoundError (#6380)

* check parameterTypesDesc of Generic and Echo  (#6374)

* add tps filter to SPI list (#6282)

* Do not clear all configurator  instances when override is empty (#6395)

* Service callback throws "Not found exported service" when 'bind.port' is set (#6223)

* Removing RpcContext after test finishes. (#6314)

* Introduce ClusterInvoker to better support multiple registries subscription (#6343)

* return same reference invokers as much as possible (#6083)

fixes #6082

* fix ut

* Fixes the test-cases

* Fixes the test-cases

* Fixes the test-cases

Co-authored-by: tswstarplanet <tswstarplanet@apache.org>
Co-authored-by: Nine <nine.yang.coding@gmail.com>
Co-authored-by: 陈哈哈 <chenyongjia365@outlook.com>
Co-authored-by: luoning810 <18311333766@163.com>
Co-authored-by: cvictory <shenglicao2@gmail.com>
Co-authored-by: ken.lj <ken.lj.hz@gmail.com>
Co-authored-by: Siqu Chen <32302975+DIscord010@users.noreply.github.com>
Co-authored-by: D-H-T <dht925nerd@126.com>
Co-authored-by: skyguard1 <qhdxssm@qq.com>
Co-authored-by: Jeff Lu <278400368@qq.com>
Co-authored-by: Christophe·liwei <2484713618@qq.com>
Co-authored-by: Joe Zou <joezou@apache.org>
Co-authored-by: 李黄河 <jameslover121@gmail.com>
Co-authored-by: OrDTesters <44483852+OrDTesters@users.noreply.github.com>
Co-authored-by: zjseu2009 <zjseu2009@163.com>
@jiangyunpeng
Copy link

不好意思,请问下 2.6.x 版本不修复这个漏洞吗?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants