深入探讨Handlebars 4.1.2之命令执行漏洞
字数 1423 2025-08-26 22:11:14

Handlebars 4.1.2 命令执行漏洞深入分析与利用

漏洞概述

Handlebars 4.1.2 版本存在一个严重的沙箱逃逸漏洞,可导致远程代码执行。该漏洞源于Handlebars模板引擎对JavaScript原型链的不当处理,攻击者可以通过精心构造的模板绕过安全限制,执行任意JavaScript代码。

漏洞背景

Handlebars是一个弱逻辑的模板引擎,设计初衷是为模板提供限制性的沙箱环境。引擎会将模板编译为JavaScript代码,正常情况下应该严格限制用户可以执行的操作。然而,该版本存在设计缺陷,使得攻击者可以绕过这些限制。

漏洞利用目标

要成功利用此漏洞,攻击者需要完成以下任务序列:

  1. 使用始终返回true的函数覆盖propertyIsEnumerable,绕过针对NPM 755漏洞的缓解措施
  2. 获取对Function构造函数的引用
  3. 使用攻击者控制的对象来调用函数的构造函数
  4. 调用构造的函数以执行payload

漏洞利用技术细节

1. 创建初始payload

攻击者首先需要创建一个包含单个字符串元素的数组,该元素定义了要执行的JavaScript代码。这可以通过将this设置为包含payload的字符串,然后调用split方法实现:

{{#with "a"}}
  {{this.split "payload"}}
{{/with}}

2. 滥用helper函数

Handlebars中的with helper函数类似于JavaScript中的with操作符,但有一个关键区别:如果将函数传递给with helper,它会直接调用该函数(不带参数),并使用返回值作为上下文,而不是函数本身。

这意味着:

{{#with something}}
  {{something}}
{{/with}}

实际上等价于:

output(something())

而我们想要的是:

output(something)

3. 利用__defineGetter____lookupGetter__

这两个较少使用的JavaScript方法在此漏洞利用中扮演关键角色:

  • __defineGetter__: 定义每次访问属性时调用的函数
  • __lookupGetter__: 返回用于生成值的函数

利用代码示例:

{{__defineGetter__ "undefined" valueOf }}
{{#with __lookupGetter__ }}
  ...
{{/with}}

这会被编译为:

this.__defineGetter__("undefined", this.valueOf)
with(this.__lookupGetter__()) {
  ...
}

4. 绕过安全补丁

为了绕过针对NPM 755漏洞的补丁,攻击者需要使propertyIsEnumerable始终返回true

{{#with __lookupGetter__ }}
  {{__defineGetter__ "propertyIsEnumerable" (this.bind (this.bind 1)) }}
{{/with}}

这等价于:

valueOf.__defineGetter__("propertyIsEnumerable", valueOf.bind(valueOf.valueOf.bind(1)))
// 结果: valueOf.propertyIsEnumerable = function() { return (1).valueOf() }

5. 获取Function构造函数引用

一旦绕过补丁,攻击者就可以获取this.constructor(即Function构造函数的引用),然后调用它执行任意代码。

完整利用流程

  1. 设置上下文为valueOf函数
  2. 使用__lookupGetter__获取函数引用
  3. 覆盖propertyIsEnumerable使其始终返回true
  4. 获取Function构造函数
  5. 构造并执行恶意payload

漏洞时间线

此漏洞在5个月前已向NPM Security报告,但未收到回复。由于该漏洞需要配合模板注入漏洞才能利用,作者决定公开披露。

防御措施

  1. 立即升级到Handlebars的最新版本
  2. 对用户提供的模板输入进行严格过滤
  3. 在沙箱环境中运行Handlebars模板处理
  4. 禁用或限制危险的原型方法如__defineGetter____lookupGetter__

总结

Handlebars 4.1.2的命令执行漏洞展示了即使设计良好的沙箱环境也可能因JavaScript原型链的复杂性而被绕过。开发人员应始终保持对第三方依赖的更新,并对用户提供的模板输入保持高度警惕。

Handlebars 4.1.2 命令执行漏洞深入分析与利用 漏洞概述 Handlebars 4.1.2 版本存在一个严重的沙箱逃逸漏洞,可导致远程代码执行。该漏洞源于Handlebars模板引擎对JavaScript原型链的不当处理,攻击者可以通过精心构造的模板绕过安全限制,执行任意JavaScript代码。 漏洞背景 Handlebars是一个弱逻辑的模板引擎,设计初衷是为模板提供限制性的沙箱环境。引擎会将模板编译为JavaScript代码,正常情况下应该严格限制用户可以执行的操作。然而,该版本存在设计缺陷,使得攻击者可以绕过这些限制。 漏洞利用目标 要成功利用此漏洞,攻击者需要完成以下任务序列: 使用始终返回true的函数覆盖 propertyIsEnumerable ,绕过针对NPM 755漏洞的缓解措施 获取对 Function 构造函数的引用 使用攻击者控制的对象来调用函数的构造函数 调用构造的函数以执行payload 漏洞利用技术细节 1. 创建初始payload 攻击者首先需要创建一个包含单个字符串元素的数组,该元素定义了要执行的JavaScript代码。这可以通过将 this 设置为包含payload的字符串,然后调用 split 方法实现: 2. 滥用helper函数 Handlebars中的 with helper函数类似于JavaScript中的 with 操作符,但有一个关键区别:如果将函数传递给 with helper,它会直接调用该函数(不带参数),并使用返回值作为上下文,而不是函数本身。 这意味着: 实际上等价于: 而我们想要的是: 3. 利用 __defineGetter__ 和 __lookupGetter__ 这两个较少使用的JavaScript方法在此漏洞利用中扮演关键角色: __defineGetter__ : 定义每次访问属性时调用的函数 __lookupGetter__ : 返回用于生成值的函数 利用代码示例: 这会被编译为: 4. 绕过安全补丁 为了绕过针对NPM 755漏洞的补丁,攻击者需要使 propertyIsEnumerable 始终返回 true : 这等价于: 5. 获取Function构造函数引用 一旦绕过补丁,攻击者就可以获取 this.constructor (即 Function 构造函数的引用),然后调用它执行任意代码。 完整利用流程 设置上下文为 valueOf 函数 使用 __lookupGetter__ 获取函数引用 覆盖 propertyIsEnumerable 使其始终返回 true 获取 Function 构造函数 构造并执行恶意payload 漏洞时间线 此漏洞在5个月前已向NPM Security报告,但未收到回复。由于该漏洞需要配合模板注入漏洞才能利用,作者决定公开披露。 防御措施 立即升级到Handlebars的最新版本 对用户提供的模板输入进行严格过滤 在沙箱环境中运行Handlebars模板处理 禁用或限制危险的原型方法如 __defineGetter__ 和 __lookupGetter__ 总结 Handlebars 4.1.2的命令执行漏洞展示了即使设计良好的沙箱环境也可能因JavaScript原型链的复杂性而被绕过。开发人员应始终保持对第三方依赖的更新,并对用户提供的模板输入保持高度警惕。