| Título | meteor https://www.meteor.com/ <=3.2.1 Inefficient Regular Expression Complexity |
|---|
| Descripción | # ReDoS Vulnerability in ddp-server/_clientAddress via x-forwarded-for Header
**Vulnerability Details:**
* **Type:** Regular Expression Denial of Service (ReDoS)
* **Affected Component:** `packages/ddp-server/livedata_server.js`, specifically within the `Session.prototype._clientAddress` method.
* **Vulnerable Code Snippet:**
```javascript
forwardedFor = forwardedFor.trim().split(/\s*,\s*/);
```
* **Problematic Regex:** `/\s*,\s*/`
**Condition for Exploitation:**
This vulnerability can be triggered only when the Meteor server's environment variable `HTTP_FORWARDED_COUNT` is set to an integer value greater than 0.
**Input Source & Impact:**
When the condition above is met, the code processes the `x-forwarded-for` HTTP header value. A malicious client can send a crafted `x-forwarded-for` header containing a large number of whitespace characters followed by a non-comma character. Due to catastrophic backtracking in the vulnerable regex, this can cause the server process handling the DDP connection to consume excessive CPU, leading to a Denial of Service.
**Proof of Concept (PoC):**
1. Set the `HTTP_FORWARDED_COUNT` environment variable to `1` (or higher) on the Meteor server.
2. Initiate a DDP connection to the server.
3. Include an `x-forwarded-for` HTTP header with a value consisting of a very large number of space characters followed by a non-comma character (e.g., `' '.repeat(LARGE_NUMBER) + 'a'`).
4. Observe the server process for high CPU usage and unresponsiveness.
**Suggested Fix:**
To mitigate this ReDoS risk and improve clarity, replace the regex-based split with a safer approach using `String.prototype.split` with a simple delimiter and `Array.prototype.map` for trimming:
```diff
// In packages/ddp-server/livedata_server.js, within Session.prototype._clientAddress method
// Original vulnerable line:
- forwardedFor = forwardedFor.trim().split(/\s*,\s*/);
// Suggested fix:
+ // Trim the entire string (already done before this point in the original code)
+ let parts = forwardedFor.split(',');
+ // Trim each part and filter out empty strings
+ forwardedFor = parts.map(part => part.trim()).filter(part => part.length > 0);
+
+ // Adapt the subsequent logic to use the 'parts' array instead of the direct result of split.
+ // Example assuming the original code intended to get the Nth-to-last element:
+ let clientAddress = null;
+ if (httpForwardedCount <= forwardedFor.length) {
+ clientAddress = forwardedFor[forwardedFor.length - httpForwardedCount];
+ }
+ // return clientAddress; // (Adjust based on actual return logic needed) |
|---|
| Fuente | ⚠️ https://github.com/meteor/meteor/pull/13721 |
|---|
| Usuario | DayShift (UID 80963) |
|---|
| Sumisión | 2025-05-03 03:29 (hace 12 meses) |
|---|
| Moderación | 2025-05-15 09:13 (12 days later) |
|---|
| Estado | Aceptado |
|---|
| Entrada de VulDB | 309029 [Meteor hasta 3.2.1 livedata_server.js Object.assign forwardedFor denegación de servicio] |
|---|
| Puntos | 20 |
|---|