<!-- log -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
日志文件配置如下,
下面最后一行是使用logback的高级特性直接加在logback-spring-local.xml的配置文件,如果不区分本地环境、测试环境、生产环境配置则不需要指定,详细配置可参考链接4.
logging:
# 日志输出格式
pattern:
# 文件日志输出格式: 时间格式 线程名称 日志级别 日志输出类 日志信息
file: "%d{yyyy/MM/dd-HH:mm:ss} {%thread} %-5level %logger- %msg%n"
console: "%d{yyyy/MM/dd-HH:mm:ss} {%thread} %-5level %logger- %msg%n"
# 配置日志生成路径,下一日运行时会把前一日的日志文件打包成压缩包
file:
name: /Users/kaizhang/workspace/log/basic.log
# 配置日志输出级别,error以上级别输出 ,默认输出日志级别:INFO(即包含INFO<WARING<ERROR)
level:
# 默认全局
root: error
# 在指定类下最低日志输出级别
com.hust.zhang.web.controller.HomeController: debug
# 加载指定目录下的日志输出配置文件
# config: classpath:log/logback-spring-local.xml
CVE-2021-44228
官方解释:When the logging configuration uses a non-default Pattern Layout with a Context Lookup (for example, $${ctx:loginId}), attackers with control over Thread Context Map (MDC) input data can craft malicious input data using a JNDI Lookup pattern, resulting in an information leak and remote code execution in some environments and local code execution in all environments; remote code execution has been demonstrated on macOS but no other tested environments.
CVE(Common Vulnerabilities & Exposures)通用漏洞披露是一个字典表,记录着广泛认同的信息安全漏洞,上面相当于全球注册的唯一标识标记该漏洞。
LDAP
LDAP(Lightweight Directory Access Protocol,轻量级目录访问协议)是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。
常见的应用场景是进行统一登录,参看:LDAP认证登录 - 应用身份服务 - 阿里云
JNDI
JNDI(Java Naming And Directory Interface,Java命名服务和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口(SPI,Serial Peripheral Interface)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。
JDBC连接数据库的弊端:
- 参数变动引发URL修改
- 数据库产品切换,驱动包修改(eg:mysql —> oracle)
- 连接池参数的调整
由于JDBC连接数据库存在一些弊端,所以可以通过JNDI来实现命名服务和目录服务的交互。
命名服务
命名服务用于根据名字找到位置、服务、信息、资源、对象。
- 发布服务bind
- 查找服务lookup
比如使用JDNI方式去建立数据库连接,在application.yaml文件中配置spring.datasource.jndi-name属性
spring:
application:
name: hust-zhang
profiles:
active: local
datasource:
jndi-name: jdbc/exampleDB
配置中加载的命名服务是在context.xml里配置的资源
<Context>
<!-- apache-tomcat/config/context.xml -->
<Resource name="jdbc/exampleDB"
auth="Container"
type="javax.sql.DataSource"
username="root"
password="123456"
driverNameClass="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/testdemo"
maxTotal="8"
maxIdle="4"/>
</Context>
JNDI提供的接口屏蔽了访问底层的一些细节,对于application.yaml文件来说配置始终不变,需要改的是目录服务中的context.xml配置。
JNDI动态协议转换
当我们调用lookup()方法时,如果lookup方法的参数像demo中那样是一个uri的地址,那么客户端就会去lookup()方法参数指定的uri中加载远程对象。
JNDI Naming Reference命名引用
当有客户端通过lookup(“refObj”)获取远程对象时,获取的是一个Reference存根(Stub),由于是Reference的存根,所以客户端会先在本地的classPath中去检查是否存在类refClassName,如果不存在则去指定的url动态加载。
JNDI注入
JNDI注入流程如下图所示,调用JNDI接口时传入恶意参数,访问目录服务获取Reference存根。然后访问LDAP目录服务中不存在的refClassName。从指定地址动态加载Exploit对象,Exploit对象的静态代码块可以执行打开计算器操作。RMI(Remote Method Invocation,远程方法调用)也可以通过这种方式实现攻击。
public class Exploit {
static {
try {
// 适用于windows系统命令行打开计算器