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年 - 17571 ]はApacheのLog4j 1.2 信頼できないデータのデシリアライズ でSocketServer CVE - 2019 - 17571:信頼できないデータのデシリアライゼーションでSocketServer 重要度:重大 CVSS:3.0 / AV:N / AC:L / PR:N / UI:N / S:U / C :H / I:H / A:H / RL:W 製品: ApacheのLog4jのの 影響を受けるバージョン: ApacheのLog4jのまでを含む1.2。27。別に固定で CVE - 2017年 - 5645 でのLog4j 2.8。2 。 問題のタイプ: CWE - 502 :信頼できないデータのデシリアライズ 説明: 含まに Log4jの1.2 である SocketServerのクラスであるに弱い 遠隔的に利用することができる、信頼できないデータのデシリアライゼーション デシリアライゼーションガジェットと組み合わせた場合に任意のコードを実行します 信頼できないネットワークトラフィックを聴くときのためにログデータ。 緩和: ApacheのLog4jの1.2は、人生の最後に到達して年8月2015年までに。ユーザーは、必要がある のLog4jにアップグレード2 .Xアドレスその脆弱性の両方としてだけでなく として、他の多くの問題で以前のバージョン。 クレジット: この問題が最初に発見された中で CVE- 2017年 - 5645 マルシオ・アルメイダによって テルストラでレッドチームのデMacedo。 リンク: HTTPS:// logging.apache.org/log4j/1.2/ HTTPS:// issues.apache.org/jira/browse/LOG4J2-1863 - マット・重症 長官、Apache Software Foundationの VPロギングサービス、ASF
SocketServerクラスの脆弱性
Log4jのjarファイルパッケージをダウンロードしてください。私は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是输入流。
因此只要传入的字节流是反序列化的内容即可。