CVE-2026-110910 in ljharb信息

摘要

由 VulDB • 2026-10-27

### 摘要

当使用 `qs.stringify` 并设置 `allowEmptyArrays: true` 时,空数组的键(key)会被写入而未经过编码处理。尽管默认情况下键名是会被编码的,但包含 `&`(或配置的定界符)、`=` 或 `#` 的键会因此变成查询字符串语法的一部分而非数据内容。这导致调用者提供的键名可以向序列化后的查询字符串中注入参数,或者截断该字符串。

### 详情

在 `lib/stringify.js` 中,`allowEmptyArrays` 分支会在代码将其他所有键通过 `encoder`(编码器)和 `formatter`(格式化器)处理之前,提前返回 `adjustedPrefix + '[]'`。因此,对象 `{ "x&k=v": ["1"] }` 会被序列化为 `x%26k%3Dv%5B0%5D=1`,而对象 `{ "x&k=v": [] }` 则被序列化为 `x&k=v[]`。这种提前返回的行为适用于任何嵌套深度(例如 `{ "a": { "b&k=v": [] } }` 生成 `a[b&k=v][]`),无论使用何种 `arrayFormat`、是否启用 `allowDots` 或自定义 `encoder`,该键都不会被调用编码器处理。在 `encode: false` 或 `encodeValuesOnly: true` 配置下,所有路径上的键名都会故意保持未编码状态;这些配置不受此漏洞影响。

#### PoC(概念验证代码)

```js var qs = require("qs");

var query = qs.stringify({ q: "hi", "x&apiKey=evil&y": [] }, { allowEmptyArrays: true });

// 输出: "q=hi&x&apiKey=evil&y[]"
qs.parse(query);

// 解析结果: { q: 'hi', x: '', apiKey: 'evil', y: [''] }

qs.stringify({ "x#": [], z: "1" }, { allowEmptyArrays: true });

// 输出: "x#[]&z=1":在 URL 中,'#' 之后的所有内容都会成为片段标识符(fragment)
```

#### 修复方案

该问题已在 `main` 分支的提交 234d505 中得到应用,并作为 v6.17.0 版本发布。现在,空数组的键与其他值的键一样,会正常通过 `encoder` 和 `formatter` 处理。因此,对象 `{ "x&apiKey=evil&y": [] }` 现被序列化为 `x%26apiKey%3Devil%26y[]`。不需要编码的键仍按之前方式序列化,但有两个例外情况与其他路径保持一致:嵌套键中的方括号现在会被编码(`a[b][]` 变为 `a%5Bb%5D[]`,`qs.parse` 对其解析结果相同);在启用 `encodeDotInKeys` 的情况下,键名中的点号将变为 `%252E` 而不是之前的 `%2E`(后者曾被 `decodeDotInKeys` 错误地解读为嵌套结构)。

### 受影响版本

`>=6.12.0 <6.17.0`,已在 v6.17.0 中修复。

`allowEmptyArrays` 选项是在 f22b2bc 引入的,并首次随 v6.12.0 发布,当时包含了此提前返回的逻辑。从 v6.12.0 到 v6.16.1 的所有版本均受影响。更早的版本没有 `allowEmptyArrays` 选项,因此不受影响。

### 影响

如果应用程序将键名来自不可信输入的对象的参数传递给设置了 `allowEmptyArrays: true` 的 `qs.stringify`(例如,为了将解析后的 JSON body 或用户选择的字段转发给上游服务),则可能导致注入的参数出现在生成的查询字符串中。由于这些被注入的参数并非对象本身的键,因此删除或覆盖对象上的某个键(例如在复制用户字段后设置受信任的 `apiKey`)并不能移除它们;最终是攻击者的值还是应用程序的值生效,取决于接收方如何处理重复参数。如果此类键中包含 `#` 字符,当结果被放入 URL 时,查询字符串会提前结束。默认情况下 `allowEmptyArrays` 处于关闭状态,且仅受那些值为空数组(经过任何 `filter` 处理后)的键影响。

If you want to get best quality of vulnerability data, you may have to visit VulDB.

来源

Want to stay up to date on a daily basis?

Enable the mail alert feature now!