这里:https:
关于在 log4j 中使用字符串连接,他们是这样说的:
更重要的是,这种方法很容易受到攻击!想象一下用户提供的 userId 包含以下内容:不存在的参数的占位符会触发失败:{} {} {dangerousLookup}
有人能解释一下为什么这很危险吗?我不明白字符串连接与这个“dangerousLookup”有什么关系。
2
最佳答案
3
我认为文档非常清楚
假设用户提供的 userId 包含以下内容:不存在的参数占位符会触发失败:{} {}
如果你有以下记录器并且通过了上面的userId
LOGGER.info("failed for user ID: " + userId);
代码执行将会中断,因为记录器将以内容的形式出现,"failed for user ID: placeholders for non-existing args to trigger failure: {} {} "
并且记录器将引发异常,即未提供所需的 2 个参数。
此外,正如评论者Violet所提到的,有人甚至可以传递带有动态评估的连接参数。某些内容不应该打印在日志中,例如,${env:SECRET_ENV_VAR}
危险查找中提到的情况。
您还可以将以上两者结合起来,看看某人如何使用记录器中抛出的异常,该记录器向用户提供异常的信息,以获取原本应该隐藏的信息。
这就是为什么他们建议要求信息的布局是具体的,而不是控制论点。例如
LOGGER.info("failed for user ID `{}`", userId);
现在,记录器将仅打印布局中描述的提供的参数userId
,并且不会将其与布局混合,以便保护您免受上述和其他几个问题的影响。
3
-
1在某些情况下,您甚至可以引用 JNDI 并从远程机器加载类。
– -
@talexmovedtoCodidact:确实对字符串连接和参数化日志记录产生了同等影响。
– -
@Panagiotis Bougioukos:由于参数数量不匹配而引发的抛出行为在
2.23.0
Log4j Core 版本中短暂出现过,并在版本中被警告所取代2.23.1
(请参阅)。
–
|
文档令人困惑,感谢您报告问题。字符串连接和参数化日志记录本身都没有安全隐患。但是,当您将两者混合使用时,就会出现问题:
logger.warn("Login failed for user '" + user + "' from remote address '{}'.", remoteIp);
如果攻击者{}
以用户身份发送,您将收到类似以下消息:
Login failed for user '192.0.2.1' from remote address '{}'.
这是一个轻微的漏洞,但它可能会给自动日志解析器带来问题或使管理员感到困惑。如果您使用参数化日志记录,则格式字符串应该是编译时常量。
如果仅使用字符串连接或参数化日志记录,则不会出现此类问题:
// String concatenation
logger.warn("Login failed for user '" + user + "' from remote address '" + remoteIp + "'.");
// Parameterized logging
logger.warn("Login failed for user '{}' from remote address '{}'.", user, remoteIp);
两者都将返回:
Login failed for user '{}' from remote address '192.0.2.1'.
注意:如果日志文件被自动解析,并且日志消息的参数有意义,建议使用和。
|
如果您使用字符串连接(如链接的示例所示),并且连接的变量的值可能来自您无法控制的外部源,则攻击者可以使该值具有占位符,log4j 的日志记录方法将照常处理这些占位符,并且该占位符可能包含利用 log4j 中的漏洞的恶意代码。然后,该恶意代码将被执行,攻击者将获得利用该漏洞的好处。这就是其含义{dangerouslookup}
,大概是指 log4j 中过去使用 JNDI 查找作为攻击媒介的漏洞。
|
${env:SECRET_ENV_VAR}
)。因此,您不应将任何您无法控制的内容连接到它。–
–
|