semgrep 分析log4j2

admin 2022年3月25日23:55:32评论164 views字数 3008阅读10分1秒阅读模式

semgrep 分析log4j2

看到很多师傅都是使用codeql 来找log4j2 shell 的Sink和Source,例如FreeBuf 上的文章《codeql分析log4j 》https://www.freebuf.com/articles/web/318141.html 、先知社区《利用CodeQL分析并挖掘Log4j漏洞》https://xz.aliyun.com/t/10707 。但是好像没看到有人使用semgrep 来分析log4j的,因此就来尝试使用semgrep看看能否很容易地找到Sink和Source。


题外话:发现semgrep 网站上也有了专门针对log4j2 shell 漏洞检测规则,https://semgrep.dev/editor?registry=java.log4j.security.log4j-message-lookup-injection.log4j-message-lookup-injection 。怎么说呢,这个规则可以用于前期应急的时候代码检测,但是后期就没办法知道哪些升级了哪些没升级,是否用的是安全版本了。

semgrep 分析log4j2

环境搭建

相比codeql 需要对log4j源码进行编译生成代码数据库的过程,semgrep 不需要对需要分析的代码进行编译的,因此直接把logging-log4j2-rel-2.14.1 这个版本的源码下载到本地即可,非常简单。

这里我使用semgrep  docker 方式部署来进行代码扫描的:

docker run --rm -v "${PWD}:/src" returntocorp/semgrep --config=s/xx  ./  -o scan-c.txt  --time --debug

关于semgrep 的更多详细使用方式可参考我之前的文章 https://www.freebuf.com/articles/web/286643.html

编写规则

当然Sink 点还是落在JNDI注入的lookup方法上,所以首先初步匹配下lookup 方法,看看能匹配出多少个lookup。

只使用一个pattern,规则也是比较容易就写出来的:

rules:- id: log4j-lookup  pattern:        $NAME.lookup(...);  message: |      find lookups  languages: [java]  severity: WARNING  metadata:       category: security      technology:        - java      confidence: MEDIUM

在调试阶段,我们可以在https://semgrep.dev/editor 上编写规则,验证好了之后可以通过share方式,然后通过--config=  去加载指定的规则。

semgrep 分析log4j2


semgrep 分析log4j2

从上图可以看到,找到了16处存在调用lookup方法的代码行位置:

semgrep 分析log4j2

优化规则

  上一步的规则找到了16处的问题,但是一个一个去分析有点多,有必要进一步筛选下。知道JNDI注入会使用JNDI context方式,其中应该都会引入javax.naming.Context 或者 javax.naming.InitialContext 类,而且InitialContext 实现了Context 接口。

因此继续改造下规则,这次我们引入patterns 关键字来进行限定:

(1)要求调用lookup方法前导入了 javax.naming.Context

 (2)   要求调用lookup方法前导入了javax.naming.InitialContext

基于上面的两种情况,编写如下规则:

rules:- id: log4j-lookup  patterns:    - pattern-either:      - patterns:              - pattern-inside: |                  import javax.naming.Context;                  ...              - pattern: $NAME.lookup(...);      - patterns:              - pattern-inside: |                  import javax.naming.InitialContext;                       ...              - pattern: $NAME.lookup(...);                message: |      find lookups  languages: [java]  severity: WARNING  metadata:       category: security      technology:        - java      confidence: MEDIUM

只需片刻时间,检测结果就出来了,这次看到只找到两处。

semgrep 分析log4j2


分别为 DataSourceConnectionSource#createConnectionSource和JndiManager#lookup

semgrep 分析log4j2

通过上述规则找到了Sink点。

  • JndiManager#lookup

 @SuppressWarnings("unchecked")    public <T> T lookup(final String name) throws NamingException {        return (T) this.context.lookup(name);    }
  • DataSourceConnectionSource#createConnectionSource

@PluginFactory    public static DataSourceConnectionSource createConnectionSource(@PluginAttribute("jndiName") final String jndiName) {        if (Strings.isEmpty(jndiName)) {            LOGGER.error("No JNDI name provided.");            return null;        }
try { final InitialContext context = new InitialContext(); final DataSource dataSource = (DataSource) context.lookup(jndiName); if (dataSource == null) { LOGGER.error("No data source found with JNDI name [" + jndiName + "]."); return null; }
return new DataSourceConnectionSource(jndiName, dataSource); } catch (final NamingException e) { LOGGER.error(e.getMessage(), e); return null; } }

关于查找Source

     首先,semgrep 对于数据流分析能力相较Codeql 来比是很弱的,因此想找到一条完整的调用链是非常困难。它最大的魅力在于已知Source和Sink或者sanitized的情况下,可以用于自动化检查开发是否按照编码规范进行编码的工具。

最后,别忘了领取下红包封面,祝愿2022年万事如意,平安顺遂!


往期推荐文章:

原文始发于微信公众号(风藤安全):semgrep 分析log4j2

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年3月25日23:55:32
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   semgrep 分析log4j2http://cn-sec.com/archives/841564.html

发表评论

匿名网友 填写信息