CVE-2019-17571 역 직렬화에서 Log4j의 구성 요소

https://www.openwall.com/lists/oss-security/2019/12/19/2

날짜 : 수요일, (18) 년 12 월 2019 년  21 : 21 : (19) - 0600 
에서 : 매트 아프고 <mattsicker @ ... che.org> 
받는 사람 : OSS - 보안 @ ... ts.openwall.com 
제목 : [CVE - 2019 년 - 1만7천5백71 ] 아파치 Log4j는 1.2 신뢰할 수없는 데이터의 직렬화
  SocketServer 

CVE - 2019 - 1만7천5백71 : 신뢰할 수없는 데이터의 직렬화 SocketServer 

심각도 : 긴급 
CVSS : 3.0 / AV : N / AC : L / PR : N / UI : N / S : U / C : H / I : H / A : H / RL : W

제품 : 
아파치의 Log4j 

버전 영향을받는 : 
아파치의 log4j에 포함 최대 1.2 . (27) . 별도로 고정 에 의해 
CVE - 2017 년 - 5645   의 log4j 2.8 . 2 . 

문제 유형 : 
CWE - 502 : 신뢰할 수없는 데이터를 역 직렬화 

설명 : 

포함됨  Log4j는 1.2  이다 SocketServer의 클래스 이다 취약  
원격으로 이용 될 수있는 신뢰할 수없는 데이터의 직렬화
역 직렬화 가제트과 결합 될 때, 임의의 코드를 실행할
신뢰할 수없는 네트워크 트래픽을들을 때 에 대한 로그 데이터. 

완화 : 

아파치의 log4j 1.2은 수명이 다한  년 8 월 2015 년 . 사용자해야 
Log4j를로 업그레이드 2 .x를을하는 두 주소 취약점 그 뿐만 아니라
 같은 많은 다른 문제 이전 버전. 

신용 : 

이 문제는 처음 발견 된  CVE- 2017 년 - 5645 마르시오 알메이다에 의해 
텔스트라 (Telstra)에서 레드 팀의 드 마세. 

링크 : 

HTTPS : // logging.apache.org/log4j/1.2/
HTTPS : // issues.apache.org/jira/browse/LOG4J2-1863
 
-  
매트 아프고 
장관, 아파치 소프트웨어 재단 
부사장 서비스 로깅, ASF

SocketServer 클래스의 취약점

Log4j의 항아리 패키지를 다운로드합니다. 나는 1.2.14 버전을 선택했다.

SocketServer.class에 글로벌 검색

 

 

클래스 코드를 볼 수있는 코드의 주요 기능은, 코드가 아주 잘 이해 오래되지 않습니다.

  void main(String argv[]) {
    if(argv.length == 3)
      init(argv[0], argv[1], argv[2]);
    else
      usage("Wrong number of arguments.");

    try {
      cat.info("Listening on port " + port);
      ServerSocket serverSocket = new ServerSocket(port);
      while(true) {
    cat.info("Waiting to accept a new client.");
    Socket socket = serverSocket.accept();
    InetAddress inetAddress =  socket.getInetAddress();
    cat.info("Connected to client at " + inetAddress);

    LoggerRepository h = (LoggerRepository) server.hierarchyMap.get(inetAddress);
    if(h == null) {
      h = server.configureHierarchy(inetAddress);
    }

    cat.info("Starting new socket node.");
    new Thread(new SocketNode(socket, h)).start();
      }
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }

init初始化了参数,传入的参数是三个。

new一个serverSocket对象,最后new Thread(new SocketNode(socket, h)).start();

把收到的socket流内容,用SocketNode实例化这个流内容。我们看下SocketNode这个类是怎么实现的吧。全局搜索SocketNode。

public class SocketNode implements Runnable {

  Socket socket;
  LoggerRepository hierarchy;
  ObjectInputStream ois;

  static Logger logger = Logger.getLogger(SocketNode.class);

  public SocketNode(Socket socket, LoggerRepository hierarchy) {
    this.socket = socket;
    this.hierarchy = hierarchy;
    try {
      ois = new ObjectInputStream(
                         new BufferedInputStream(socket.getInputStream()));
    }
    catch(Exception e) {
      logger.error("Could not open ObjectInputStream to "+socket, e);
    }
  }

  //public
  //void finalize() {
  //System.err.println("-------------------------Finalize called");
  // System.err.flush();
  //}

  public void run() {
    LoggingEvent event;
    Logger remoteLogger;

    try {
      while(true) {
    // read an event from the wire
    event = (LoggingEvent) ois.readObject();
    // get a logger from the hierarchy. The name of the logger is taken to be the name contained in the event.
    remoteLogger = hierarchy.getLogger(event.getLoggerName());
    //event.logger = remoteLogger;
    // apply the logger-level filter
    if(event.getLevel().isGreaterOrEqual(remoteLogger.getEffectiveLevel())) {
      // finally log the event as if was generated locally
      remoteLogger.callAppenders(event);
    }
      }
    } catch(java.io.EOFException e) {
      logger.info("Caught java.io.EOFException closing conneciton.");
    } catch(java.net.SocketException e) {
      logger.info("Caught java.net.SocketException closing conneciton.");
    } catch(IOException e) {
      logger.info("Caught java.io.IOException: "+e);
      logger.info("Closing connection.");
    } catch(Exception e) {
      logger.error("Unexpected exception. Closing conneciton.", e);
    }

    try {
      ois.close();
    } catch(Exception e) {
      logger.info("Could not close connection.", e);
    }
  }
}

代码不是很长,执行的是run的代码。可以看到

event = (LoggingEvent) ois.readObject();

直接执行了readObject操作。ois是ObjectInputStream ois;定义了ois是输入流。

因此只要传入的字节流是反序列化的内容即可。

추천

출처www.cnblogs.com/ph4nt0mer/p/12125241.html