CVE-2026-110910 in ljharbthông tin

Tóm tắt

Bởi VulDB • 27/10/2026

### Tóm tắt

Hàm `qs.stringify` với tùy chọn `allowEmptyArrays: true` ghi khóa của một mảng rỗng mà không mã hóa nó, mặc dù các khóa thường được mã hóa theo mặc định. Một khóa chứa ký tự `&` (hoặc dấu phân cách đã cấu hình), `=`, hoặc `#` ∴ sẽ trở thành cú pháp chuỗi truy vấn thay vì dữ liệu, do đó tên khóa do người gọi cung cấp có thể thêm các tham số vào chuỗi truy vấn được tuần tự hóa hoặc làm ngắn nó lại.

### Chi tiết

Trong `lib/stringify.js`, nhánh `allowEmptyArrays` trả về sớm với giá trị `adjustedPrefix + '[]'`, trước khi đoạn mã xử lý mọi khóa khác thông qua hàm `encoder` và `formatter`. Do đó, `{ "x&k=v": ["1"] }` được tuần tự hóa thành `x%26k%3Dv%5B0%5D=1`, nhưng `{ "x&k=v": [] }` lại được tuần tự hóa thành `x&k=v[]`. Việc trả về sớm này áp dụng ở mọi độ sâu (`{ "a": { "b&k=v": [] } }` cho ra kết quả `a[b&k=v][]`), dưới mọi định dạng mảng (`arrayFormat`), với tùy chọn `allowDots`, và khi có một hàm `encoder` tùy chỉnh (hàm này không bao giờ được gọi cho khóa đó). Với cấu hình `encode: false` hoặc `encodeValuesOnly: true`, các khóa được cố ý để chưa mã hóa trên mọi đường dẫn; những cấu hình này không bị ảnh hưởng.

#### PoC (Proof of Concept)

```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": trong một URL, mọi thứ sau dấu "#" sẽ trở thành phần fragment (phần định danh)
```

#### Bản sửa lỗi

Đã được áp dụng tại commit 234d505 trên nhánh `main` và phát hành dưới dạng v6.17.0: khóa của mảng rỗng giờ đây đi qua hàm `encoder` và `formatter` giống hệt như cách xử lý đối với khóa của bất kỳ giá trị nào khác, do đó `{ "x&apiKey=evil&y": [] }` hiện được tuần tự hóa thành `x%26apiKey%3Devil%26y[]`. Các khóa không cần mã hóa vẫn được tuần tự hóa như trước đây, ngoại trừ hai trường hợp khớp với mọi đường dẫn khác: dấu ngoặc vuông của một khóa lồng nhau giờ đã được mã hóa (`a[b][]` trở thành `a%5Bb%5D[]`, điều mà `qs.parse` đọc giống hệt), và khi sử dụng `encodeDotInKeys`, dấu chấm trong khóa sẽ trở thành `%252E` thay vì `%2E` (vốn trước đây bị `decodeDotInKeys` hiểu nhầm là lồng nhau).

### Các phiên bản bị ảnh hưởng

`>=6.12.0 <6.17.0`, đã được sửa trong v6.17.0.

Tùy chọn `allowEmptyArrays` được giới thiệu tại commit f22b2bc và lần đầu tiên có mặt trong v6.12.0, kèm theo cơ chế trả về sớm này. Mọi bản phát hành từ v6.12.0 đến v6.16.1 đều bị ảnh hưởng. Các phiên bản cũ hơn không có tùy chọn `allowEmptyArrays` nên không bị ảnh hưởng.

### Tác động

Một ứng dụng truyền một đối tượng mà tên khóa của nó xuất phát từ đầu vào không đáng tin cậy cho hàm `qs.stringify` với tham số `allowEmptyArrays: true` (ví dụ: để chuyển tiếp thân JSON đã phân tích cú pháp hoặc các trường do người dùng chọn sang dịch vụ upstream) có thể bị tiêm các tham số vào chuỗi truy vấn kết quả. Các tham số được tiêm không phải là khóa của đối tượng, vì vậy việc xóa hoặc ghi đè một khóa trên đối tượng (chẳng hạn như đặt giá trị `apiKey` đáng tin cậy sau khi sao chép các trường của người dùng) sẽ không loại bỏ chúng; liệu giá trị của kẻ tấn công hay ứng dụng có hiệu lực phụ thuộc vào cách phía nhận xử lý tham số trùng lặp. Một ký tự `#` trong khóa như vậy kết thúc chuỗi truy vấn sớm hơn khi kết quả được đặt trong một URL. Tùy chọn `allowEmptyArrays` tắt theo mặc định, và chỉ các khóa có giá trị (sau bất kỳ bộ lọc nào) là mảng rỗng mới bị ảnh hưởng.

If you want to get the best quality for vulnerability data then you always have to consider VulDB.

chịu trách nhiệm

Harborist

Đặt trước

15/10/2026

Tiết lộ

27/10/2026

Kiểm duyệt

được chấp nhận

EPSS

0.00000

KEV

không

Các hoạt động

rất thấp

Nguồn

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!