静态分析

使用污点分析检查log4j问题

2022-02-17  本文已影响0人  Uncle_Tom

【摘要】 log4j问题的余波还在继续,为什么这个问题潜伏了这么长时间,大家一直没有发现?这里从静态分析的角度谈下log4j问题的发现.

1. JNDI注入

这次log4j的问题主要是由于JNDI问题造成的,先介绍下JNDI。

1.1. JNDI

1.2. JNDI注入

JNDI 通过InitialContext.lookup(String name)函数输入的字符串参数进行初始化。如果该参数来自不受信任的源,则可能通过远程类加载导致远程代码执行。当请求对象的名称由攻击者控制时,可能会将受害者Java应用程序指向恶意RMI/LDAP/CORBA服务器,并使用任意对象进行响应。

1.3. log4j的JDNI注入

本次log4j的JNDI注入问题,就是因为当log4j的日志输出为"${xxx}"的时候,log4j会认为这是个JNDI调用的标志,并将xxx解析为JNDI资源后,加载运行。如果xxx为恶意服务地址的时候,危害也就发生了。

2. 污点分析

污点分析(Taint analysis)可以被看作是信息流分析(Information Flow Analysis)的一种,主要是追踪数据在程序中的走向。

在漏洞分析中,使用污点分析技术将所感兴趣的数据(通常来自程序的外部输入)标记为污点数据,然后通过跟踪和污点数据相关的信息的流向,可以知道它们是否会影响某些关键的程序操作,进而挖掘程序漏洞。即将程序是否存在外部输入导致漏洞的问题,转化为污点信息是否会被 Sink 点上的操作所使用的问题。

污点分析技术目前主要有静态和动态分析两种方式。本文主要讲述通过静态分析工具所采用的静态分析方法。

2.1. 污点分析的主要概念

通常外部输入数据都被认为是一种可能引起安全风险的源头,被称为污染源。这些信息被程序的接收或处理函数收到后,在程序内部通过程序内部的各个功能模块被加工、处理或调用某些外部接口执行。这些信息如果未做有效的检验就可能造成各类安全风险。

下图是污染分析在分析污染传播的过程中所经历的主要过程,这个过程被划分为:污染源、污染传播、污染清理、污染爆发。
[图片上传失败...(image-a82a19-1645184522593)]

image

2.1.1. 污染场景

2.1.2. 污染源

污染的信息会通过应用软件特定的函数被引入到应用系统中,这也是污染分析的起点。静态分析工具中,通常采用下面的方法完成污染源的定义:

2.1.3. 污染传播

污染传播是污染分析中最复杂的一个阶段,主要分为显示分析和隐式分析。

在显示分析和隐式分析中,都不可避免的会遇到:内置函数、第三方函数,以及应用框架的问题。

内置函数、第三方函数,以及应用框架都会造成分析中断的问题,从而使污染分析不能有效的进行。为了解决这个问题,静态分析软件需要定义这些函数,帮助分析程序完成污染传播的继续分析。

这些函数的定义方式基本和污染源的定义方式相同,采用配置的方式匹配到这些函数,同时还需要明确这些函数污染传入的参数和传出的参数。以方便静态分析软件在碰到这些函数时,根据传出参数继续分析。

2.1.4. 污染清理

在编程的过程中,如果对于不安全的外部输入,已经做了相应的处理,但如果静态分析工具无法知道这些检查和处理,仍然给出告警,将成为误报。这样的场景会增加分析的成本。所以在程序分析的过程中,需要对污染清理做出分析,以便减少不必要的误报,同时还可以提高分析效率。

污染清理主要分为两种处理方式:

对于清理函数的处理,同样可以采用配置的方式完成。分析程序对适配到的函数,做污染标记清楚就可以了,使静态分析工具在经过这些函数后,不再带有继续分析的标记,终止后续的分析。

2.1.5. 污染爆发

当污染经过传播仍然进入到一些特定的函数或语句时,就会引发安全漏洞的发生。这些安全漏洞主要有:

例如:输入中指定数量的不正确验证 - (1284); 输入中指定索引、位置或偏移量的不正确验证 - (1285)等。

例如:不检查输入大小的缓冲区复制(“经典缓冲区溢出”) - (120); 整数溢出导致缓冲区溢出 - (680)等。

例如:在命令中使用的特殊元素转义处理不恰当(“命令注入”) - (77); SQL 命令中使用的特殊元素转义处理不恰当(“SQL 注入”) - (89)等。

例如:使用外部控制输入来选择类或代码(“不安全反射”) - (470);不可信数据的反序列化 - (502)。 这次的log4j JNDI问题被NVD定义的CWE就是CWE 502。

3. log4j的问题分析

3.1. 测试代码

$ git clone --branch rel/2.14.1 https://gitbox.apache.org/repos/asf/logging-log4j2.git

package org.apache.logging;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class testJndi {
    private static final Logger LOG = LogManager.getLogger();

    public static void main (String[] args){
        LOG.error("${jndi:xxx}");
    }
}

3.2. 调用链

4. 思考

5. 参考

上一篇 下一篇

猜你喜欢

热点阅读