Log4j漏洞源码分析
Log4j漏洞源码分析
这几天Log4j的问题消息满天飞,今天我们就一起来看看从源码角度看看这个漏洞是如何产生的。
大家都知道这次问题主要是由于Log4j中提供的jndi的功能。
具体涉及到的入口类是log4j-core-xxx.jar中的org.apache.logging.log4j.core.lookup.StrSubstitutor这个类。
原因是Log4j提供了Lookups的能力(关于Lookups可以点这里去看官方文档的介绍),简单来说就是变量替换的能力。
在Log4j将要输出的日志拼接成字符串之后,它会去判断字符串中是否包含${和},如果包含了,就会当作变量交给org.apache.logging.log4j.core.lookup.StrSubstitutor这个类去处理。
相关的代码下面这个
首先是org.apache.logging.log4j.core.pattern.MessagePatternConverter这个类的format方法

图中标注1的地方就是现在漏洞修复的地方,让noLookups这个变量为true,就不会进去里面的逻辑,也就没有这个问题了。
图中标注2的地方就是判断字符串中是否包含
${,如果包含,就将从这个字符开始一直到字符串结束,交给图中标注3的地方去进行替换。图中标注3的地方就是具体执行替换的地方,其中
config.getStrSubstitutor()就是我们上面提到的org.apache.logging.log4j.core.lookup.StrSubstitutor。
在StrSubstitutor中,首先将${和}之间的内容提取出来,交给resolveVariable这个方法来处理。

我们看下resolver的内容,它是org.apache.logging.log4j.core.lookup.Interpolator类的对象。

它的lookups定义了10中处理类型,还有一个默认的defaultLoopup,一种11中。如果能匹配到10中处理类型,就交给它们去处理,其他的都会交给defaultLookup去处理。
匹配规则也很简单,下面简单举个例子。
1.如果我们的日志内容中有${jndi:rmi://127.0.0.1:1099/hello}这些内容,去掉
${和},传递给resolver的就是jndi:rmi://127.0.0.1:1099/hello。2.
resolver会将第一个:之前的内容和lookups做匹配,我们这里获取到的是jndi,就会将剩余部分jndi:rmi://127.0.0.1:1099/hello交给jdni的处理器JndiLookup去处理。

图中标注1的地方入参就是jndi:rmi://127.0.0.1:1099/hello
图中标注2的地方就是jndi
图中标注3的地方就是rmi://127.0.0.1:1099/hello
图中标注4的地方就是处理器
JndiLookup类的对象图中标注5的地方就是jndi来处理的入口
关于jndi相关的,以及漏洞如何复现网上有一大把的教程,这里就不展开了。
- 关于漏洞的修复。

主要是通过设置noLookups变量的值,不让它进去这个if里面的逻辑。
这个变量的值是来自下面这个属性

所以在在代码中加入System.setProperty("log4j2.formatMsgNoLookups","true");这句也就可以了。当然网上有更多其他的修复方法,这里就不讨论了。
Log4j漏洞源码分析的更多相关文章
- Apache Log4j 远程代码执行漏洞源码级分析
漏洞的前因后果 漏洞描述 漏洞评级 影响版本 安全建议 本地复现漏洞 本地打印 JVM 基础信息 本地获取服务器的打印信息 log4j 漏洞源码分析 扩展:JNDI 危害是什么? GitHub 项目 ...
- java 日志体系(四)log4j 源码分析
java 日志体系(四)log4j 源码分析 logback.log4j2.jul 都是在 log4j 的基础上扩展的,其实现的逻辑都差不多,下面以 log4j 为例剖析一下日志框架的基本组件. 一. ...
- commons-logging + log4j源码分析
分析之前先理清楚几个概念 Log4J = Log For Java SLF4J = Simple Logging Facade for Java 看到Facade首先想到的就是设计模式中的门面(Fac ...
- angular源码分析:angular中脏活累活承担者之$parse
我们在上一期中讲 $rootscope时,看到$rootscope是依赖$prase,其实不止是$rootscope,翻看angular的源码随便翻翻就可以发现很多地方是依赖于$parse的.而$pa ...
- YARN DistributedShell源码分析与修改
YARN DistributedShell源码分析与修改 YARN版本:2.6.0 转载请注明出处:http://www.cnblogs.com/BYRans/ 1 概述 2 YARN Distrib ...
- Nmap源码分析(脚本引擎)
Nmap提供了强大的脚本引擎(NSE),以支持通过Lua编程来扩展Nmap的功能.目前脚本库已经包含300多个常用的Lua脚本,辅助完成Nmap的主机发现.端口扫描.服务侦测.操作系统侦测四个基本功能 ...
- springmvc源码分析
Spring MVC源码分析--初始化过程 标签: springmvcconstructioniocclass 2012-09-09 21:32 26578人阅读 评论(3) 收藏 举报 版权声明:本 ...
- Solr4.8.0源码分析(15) 之 SolrCloud索引深入(2)
Solr4.8.0源码分析(15) 之 SolrCloud索引深入(2) 上一节主要介绍了SolrCloud分布式索引的整体流程图以及索引链的实现,那么本节开始将分别介绍三个索引过程即LogUpdat ...
- Solr4.8.0源码分析(4)之Eclipse Solr调试环境搭建
Solr4.8.0源码分析(4)之Eclipse Solr调试环境搭建 由于公司里的Solr调试都是用远程jpda进行的,但是家里只有一台电脑所以不能jpda进行调试,这是因为jpda的端口冲突.所以 ...
随机推荐
- 提升开发效率的notepad++一些快捷方法(实体类的创建和查询sql语句的编写)
新手要创建数据库表中,对应字段名的实体类,是不是感觉很麻烦,可以用notepad++快速的把实体类中的字段名进行排版,随后直接粘入idea使用 下面是navicat的演示 选择一个表,右键选择设计表 ...
- Centos8 部署 ElasticSearch 集群并搭建 ELK,基于Logstash同步MySQL数据到ElasticSearch
Centos8安装Docker 1.更新一下yum [root@VM-24-9-centos ~]# yum -y update 2.安装containerd.io # centos8默认使用podm ...
- Java安全之基于Tomcat的通用回显链
Java安全之基于Tomcat的通用回显链 写在前面 首先看这篇文还是建议简单了解下Tomcat中的一些概念,不然看起来会比较吃力.其次是回顾下反射中有关Field类的一些操作. * Field[] ...
- [atARC123F]Insert Addition
前置知识 下面,先来介绍一下Stern-Brocot Tree的结构: 其是一棵满二叉树,每一个节点都是一个最简分数,其中根为$\frac{1}{1}$ 假设前$i$层的中序遍历分数依次为$\frac ...
- Matlab矢量图图例函数quiverkey
Matlab自带函数中不包含构造 quiver 函数注释过程,本文参照 matplotlib 中 quiverkey 函数,构造类似函数为 Matlab 中 quiver 矢量场进行标注. quive ...
- Linux——基础命令用法(下)
一.linux用户 1.什么是用户 用户是用来运行某一些进程.拥有某一些文件或目录. 在Linux里面,用户分成三大类:root用户.系统用户.普通用户. 用户是用UID来唯一标识身份的,且root用 ...
- 运算符重载+日期类Date
Hello,一只爱学习的鱼 大学学习C++运算符重载的时候,老师出了一道"运算符重载+类"的综合练习题,让我们来一起看看吧! 题目: 设计一个日期类Date,包括年.月.日等私有成 ...
- abandon, aboard, abolish
abandon Abandon is a 2002 American psychological thriller drama film [惊悚片] ... Waiting for Handler o ...
- 大数据学习day11------hbase_day01----1. zk的监控机制,2动态感知服务上下线案例 3.HDFS-HA的高可用基本的工作原理 4. HDFS-HA的配置详解 5. HBASE(简介,安装,shell客户端,java客户端)
1. ZK的监控机制 1.1 监听数据的变化 (1)监听一次 public class ChangeDataWacher { public static void main(String[] arg ...
- 13个酷炫的JavaScript一行程序
1. 获得一个随机的布尔值(true/false) const randomBoolean = () => Math.random() >= 0.5; console.log(random ...