ghsa-9wv6-86v2-598j
Vulnerability from github
Impact
A bad regular expression is generated any time you have two parameters within a single segment, separated by something that is not a period (.
). For example, /:a-:b
.
Patches
For users of 0.1, upgrade to 0.1.10
. All other users should upgrade to 8.0.0
.
These versions add backtrack protection when a custom regex pattern is not provided:
They do not protect against vulnerable user supplied capture groups. Protecting against explicit user patterns is out of scope for old versions and not considered a vulnerability.
Version 7.1.0 can enable strict: true
and get an error when the regular expression might be bad.
Version 8.0.0 removes the features that can cause a ReDoS.
Workarounds
All versions can be patched by providing a custom regular expression for parameters after the first in a single segment. As long as the custom regular expression does not match the text before the parameter, you will be safe. For example, change /:a-:b
to /:a-:b([^-/]+)
.
If paths cannot be rewritten and versions cannot be upgraded, another alternative is to limit the URL length. For example, halving the attack string improves performance by 4x faster.
Details
Using /:a-:b
will produce the regular expression /^\/([^\/]+?)-([^\/]+?)\/?$/
. This can be exploited by a path such as /a${'-a'.repeat(8_000)}/a
. OWASP has a good example of why this occurs, but the TL;DR is the /a
at the end ensures this route would never match but due to naive backtracking it will still attempt every combination of the :a-:b
on the repeated 8,000 -a
.
Because JavaScript is single threaded and regex matching runs on the main thread, poor performance will block the event loop and can lead to a DoS. In local benchmarks, exploiting the unsafe regex will result in performance that is over 1000x worse than the safe regex. In a more realistic environment using Express v4 and 10 concurrent connections, this translated to average latency of ~600ms vs 1ms.
References
{ "affected": [ { "package": { "ecosystem": "npm", "name": "path-to-regexp" }, "ranges": [ { "events": [ { "introduced": "0.2.0" }, { "fixed": "1.9.0" } ], "type": "ECOSYSTEM" } ] }, { "package": { "ecosystem": "npm", "name": "path-to-regexp" }, "ranges": [ { "events": [ { "introduced": "0" }, { "fixed": "0.1.10" } ], "type": "ECOSYSTEM" } ] }, { "package": { "ecosystem": "npm", "name": "path-to-regexp" }, "ranges": [ { "events": [ { "introduced": "7.0.0" }, { "fixed": "8.0.0" } ], "type": "ECOSYSTEM" } ] }, { "package": { "ecosystem": "npm", "name": "path-to-regexp" }, "ranges": [ { "events": [ { "introduced": "2.0.0" }, { "fixed": "3.3.0" } ], "type": "ECOSYSTEM" } ] }, { "package": { "ecosystem": "npm", "name": "path-to-regexp" }, "ranges": [ { "events": [ { "introduced": "4.0.0" }, { "fixed": "6.3.0" } ], "type": "ECOSYSTEM" } ] } ], "aliases": [ "CVE-2024-45296" ], "database_specific": { "cwe_ids": [ "CWE-1333" ], "github_reviewed": true, "github_reviewed_at": "2024-09-09T20:19:15Z", "nvd_published_at": "2024-09-09T19:15:13Z", "severity": "HIGH" }, "details": "### Impact\n\nA bad regular expression is generated any time you have two parameters within a single segment, separated by something that is not a period (`.`). For example, `/:a-:b`.\n\n### Patches\n\nFor users of 0.1, upgrade to `0.1.10`. All other users should upgrade to `8.0.0`.\n\nThese versions add backtrack protection when a custom regex pattern is not provided:\n\n- [0.1.10](https://github.com/pillarjs/path-to-regexp/releases/tag/v0.1.10)\n- [1.9.0](https://github.com/pillarjs/path-to-regexp/releases/tag/v1.9.0)\n- [3.3.0](https://github.com/pillarjs/path-to-regexp/releases/tag/v3.3.0)\n- [6.3.0](https://github.com/pillarjs/path-to-regexp/releases/tag/v6.3.0)\n\nThey do not protect against vulnerable user supplied capture groups. Protecting against explicit user patterns is out of scope for old versions and not considered a vulnerability.\n\nVersion [7.1.0](https://github.com/pillarjs/path-to-regexp/releases/tag/v7.1.0) can enable `strict: true` and get an error when the regular expression might be bad.\n\nVersion [8.0.0](https://github.com/pillarjs/path-to-regexp/releases/tag/v8.0.0) removes the features that can cause a ReDoS.\n\n### Workarounds\n\nAll versions can be patched by providing a custom regular expression for parameters after the first in a single segment. As long as the custom regular expression does not match the text before the parameter, you will be safe. For example, change `/:a-:b` to `/:a-:b([^-/]+)`.\n\nIf paths cannot be rewritten and versions cannot be upgraded, another alternative is to limit the URL length. For example, halving the attack string improves performance by 4x faster.\n\n### Details\n\nUsing `/:a-:b` will produce the regular expression `/^\\/([^\\/]+?)-([^\\/]+?)\\/?$/`. This can be exploited by a path such as `/a${\u0027-a\u0027.repeat(8_000)}/a`. [OWASP](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS) has a good example of why this occurs, but the TL;DR is the `/a` at the end ensures this route would never match but due to naive backtracking it will still attempt every combination of the `:a-:b` on the repeated 8,000 `-a`.\n\nBecause JavaScript is single threaded and regex matching runs on the main thread, poor performance will block the event loop and can lead to a DoS. In local benchmarks, exploiting the unsafe regex will result in performance that is over 1000x worse than the safe regex. In a more realistic environment using Express v4 and 10 concurrent connections, this translated to average latency of ~600ms vs 1ms.\n\n### References\n\n* [OWASP](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)\n* [Detailed blog post](https://blakeembrey.com/posts/2024-09-web-redos/)", "id": "GHSA-9wv6-86v2-598j", "modified": "2024-09-12T17:09:42Z", "published": "2024-09-09T20:19:15Z", "references": [ { "type": "WEB", "url": "https://github.com/pillarjs/path-to-regexp/security/advisories/GHSA-9wv6-86v2-598j" }, { "type": "ADVISORY", "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-45296" }, { "type": "WEB", "url": "https://github.com/pillarjs/path-to-regexp/commit/29b96b4a1de52824e1ca0f49a701183cc4ed476f" }, { "type": "WEB", "url": "https://github.com/pillarjs/path-to-regexp/commit/60f2121e9b66b7b622cc01080df0aabda9eedee6" }, { "type": "WEB", "url": "https://github.com/pillarjs/path-to-regexp/commit/925ac8e3c5780b02f58cbd4e52f95da8ad2ac485" }, { "type": "WEB", "url": "https://github.com/pillarjs/path-to-regexp/commit/d31670ae8f6e69cbfd56e835742195b7d10942ef" }, { "type": "WEB", "url": "https://github.com/pillarjs/path-to-regexp/commit/f1253b47b347dcb909e3e80b0eb2649109e59894" }, { "type": "PACKAGE", "url": "https://github.com/pillarjs/path-to-regexp" }, { "type": "WEB", "url": "https://github.com/pillarjs/path-to-regexp/releases/tag/v6.3.0" } ], "schema_version": "1.4.0", "severity": [ { "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", "type": "CVSS_V3" }, { "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:P", "type": "CVSS_V4" } ], "summary": "path-to-regexp outputs backtracking regular expressions" }
Sightings
Author | Source | Type | Date |
---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
- Confirmed: The vulnerability is confirmed from an analyst perspective.
- Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
- Patched: This vulnerability was successfully patched by the user reporting the sighting.
- Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
- Not confirmed: The user expresses doubt about the veracity of the vulnerability.
- Not patched: This vulnerability was not successfully patched by the user reporting the sighting.