Dubbo 高危漏洞!原来都是反序列化惹得祸

本文详细介绍了Apache Dubbo的反序列化漏洞,包括Java反序列化漏洞的基础知识、Common-Collections库中的风险以及如何利用这些漏洞执行恶意代码。通过实例展示了如何构造攻击链路,并讨论了Dubbo的修复措施和防护策略。提醒开发者关注官方修复版本,及时升级以避免安全风险。
摘要由CSDN通过智能技术生成

前言

这周收到外部合作同事推送的一篇文章,【漏洞通告】Apache Dubbo Provider默认反序列化远程代码执行漏洞(CVE-2020-1948)通告

按照文章披露的漏洞影响范围,可以说是当前所有的 Dubbo 的版本都有这个问题。

无独有偶,这周在 Github 自己的仓库上推送几行改动,不一会就收到 Github 安全提示,警告当前项目存在安全漏洞CVE-2018-10237

可以看到这两个漏洞都是利用反序列化进行执行恶意代码,可能很多同学跟我当初一样,看到这个一脸懵逼。好端端的反序列化,怎么就能被恶意利用,用来执行的恶意代码?

这篇文章我们就来聊聊反序列化漏洞,了解一下黑客是如何利用这个漏洞进行攻击。

先赞后看,养成习惯!微信搜索『程序通事』,关注就完事了!

反序列化漏洞

在了解反序列化漏洞之前,首先我们学习一下两个基础知识。

Java 运行外部命令

Java 中有一个类 Runtime,我们可以使用这个类执行执行一些外部命令。

下面例子中我们使用 Runtime 运行打开系统的计算器软件。

// 仅适用macos 
Runtime.getRuntime().exec("open -a Calculator ");

有了这个类,恶意代码就可以执行外部命令,比如执行一把 rm /*

序列化/反序列化

如果经常使用 Dubbo,Java 序列化与反序列化应该不会陌生。

一个类通过实现 Serializable接口,我们就可以将其序列化成二进制数据,进而存储在文件中,或者使用网络传输。

其他程序可以通过网络接收,或者读取文件的方式,读取序列化的数据,然后对其进行反序列化,从而反向得到相应的类的实例。

下面的例子我们将 App 的对象进行序列化,然后将数据保存到的文件中。后续再从文件中读取序列化数据,对其进行反序列化得到 App 类的对象实例。

public class App implements Serializable {
   

    private String name;

    private static final long serialVersionUID = 7683681352462061434L;


    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
   
        in.defaultReadObject();
        System.out.println("readObject name is "+name);
        Runtime.getRuntime().exec("open -a Calculator");
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
   
        App app = new App();
        app.name = "程序通事";

        FileOutputStream fos = new FileOutputStream("test.payload");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        //writeObject()方法将Unsafe对象写入object文件
        os.writeObject(app);
        os.close();
        //从文件中反序列化obj对象
        FileInputStream fis = new FileInputStream("test.payload");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //恢复对象
        App objectFromDisk = (App)ois.readObject();
        System.out.println("main name is "+objectFromDisk.name);
        ois.close();
    }

执行结果:

readObject name is 程序通事
main name is 程序通事

并且成功打开了计算器程序。

当我们调用 ObjectInputStream#readObject读取反序列化的数据,如果对象内实现了 readObject方法,这个方法将会被调用。

源码如下:

反序列化漏洞执行条件

上面的例子中,我们在 readObject 方法内主动使用Runtime执行外部命令。但是正常的情况下,我们肯定不会在 readObject写上述代码,除非是内鬼 ̄□ ̄||

如果可以找到一个对象,他的readObject方法可以执行任意代码,那么在反序列过程也会执行对应的代码。我们只要将满足上述条件的对象序列化之后发送给先相应 Java 程序,Java 程序读取之后,进行反序列化,就会执行指定的代码。

为了使反序列化漏洞成功执行需要满足以下条件:

  1. Java 反序列化应用中需要存在序列化使用的类,不然反序列化时将会抛出 ClassNotFoundException 异常。
  2. Java 反序列化对象的 readObject方法可以执行任何代码,没有任何验证或者限制。

引用一段网上的反序列化攻击流程,来源:https://xz.aliyun.com/t/7031

  1. 客户端构造payload(有效
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值