-
-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
redos in es5-ext #201
Comments
@GAP-dev, thanks for opening that. Have you approached the real-world scenario when that happened? In normal circumstances, I believe ReDos cannot happen, as this regex is run only on function string representations where, by design, we cannot get into excessive backtracking (see that first group excludes Your test example ( Such an attack would require overriding |
Yes, This vulnerability can't exploit right now. It seems that the input string is being sanitized. However, this is a potential vulnerability. If combined with another vulnerability, it could be exploited in a real-world service. It should be implemented to further protect the system from potential attacks. It's always a good practice to assume that attackers can and will find and exploit vulnerabilities, so a defense-in-depth approach, employing multiple layers of security controls and measures, is highly recommended. |
@GAP-dev what solution do you propose? |
/^\sfunction\s+[a-zA-Z_$][0-9a-zA-Z_$]\s*([^\)])\s{/ |
@GAP-dev Version you propose is broken: const re = /^\sfunction\s+[a-zA-Z_$][0-9a-zA-Z_$]\s*([^\)])\s{/
console.log(re.test(String(function myFuńctión() { }))) Logs |
oh, sorry const regex = /function\s+([\p{L}_$][\p{L}\p{N}_$]*)\s*\(\)\s*\{\s*\}/gu;
const str = `
function myFuńctión() { }
function myfunciton() { }
function F() { }
function add() { }
`;
let m;
while ((m = regex.exec(str)) !== null) {
console.log(m[1]);
} |
@GAP-dev what you test above is not a valid function string representation, also in this package we need to support all ES5+ engines, while |
or |
const re = /^\sfunction\s(.)?\s((.))?\s*{/
console.log(re.test(String(function myFuńctión() { }))) Prints |
sorry... const re = /^\s*function\s*(.)*\s*\(([\0-(*-\uffff]*)\)\s*\{/
console.log(re.test(String(function myFuńctión() { }))) |
@GAP-dev this also won't work, as matching groups need to properly capture function name and its arguments, with what you've proposed we get |
@GAP-dev Ideally would be if you propose change as PR, as then tests will automatically pick issues for you |
Hi everyone!
|
@SCH227 Thanks for putting light on that. So, apparently, there's a real-world case where this issue can be triggered. I will work this week on fixing that. I don't think there's a reliable way to fix the regexp (if you feel otherwise, I'll be grateful for a hint). The solutions I see:
|
@medikoo, thank you for the prompt response, and for this awesome project! Your proposed solutions make sense to me. I believe they will narrow the attack surface, complex regexes are hard to debug so prone to errors. But if you want to keep them, I have these ideas:
|
Indeed, great find 👍 I didn't notice that quirk there. I believe (and as I tested) changing
This is more controversial, as functions can be defined with absurd whitespace gaps, and its stringified form will reflect that. Still, as I test, we don't have to restrict too much, e.g., we can do I believe I can go with that, and in the unlikely event of a real-world case where it appears to be breaking, I'll probably revert to a state-machine-based idea. |
Mostly I agree. |
By "backtracking payload," do you mean backtracking function body? If so, we can skip that in regex (so keep regex as you pasted in the last comment) On my side, this regex executes in 11ms for function with a string length of 30,000, and it doesn't seem to get greater for more extensive functions (I got same result for 200,000 length) |
Sorry if I was not clear enough, let me explain.
Output:
For a payload length of 20,000:
For a payload length of 200,000:
|
@SCH227, thanks for the explanations. I don't think it makes sense to take into account the Concerning other cases, after thinking it through, I think the best would be to switch to a state-machine approach, as even if we improve regex with proposed suggestions, it'll remain invalid for some ES2015+ function cases (which were not around when this utility was originally written). e.g. it'll fail for: Therefore, I think the ultimate solution would be to refactor this to esniff based version, I'll take care of it in next days |
Yes, I agree, that would be the best quality solution. Actually, my PoCs rely on the fact that the regex doesn't match some valid function cases. You can see that if there's a match, backtracking does not occurs:
|
@medikoo thank you for the fix! |
@SCH227 very good point. I've created it: GHSA-4gmj-3p3h-gm8h |
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [es5-ext](https://togithub.com/medikoo/es5-ext) | [`0.10.62` -> `0.10.63`](https://renovatebot.com/diffs/npm/es5-ext/0.10.62/0.10.63) | [![age](https://developer.mend.io/api/mc/badges/age/npm/es5-ext/0.10.63?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/es5-ext/0.10.63?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/es5-ext/0.10.62/0.10.63?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/es5-ext/0.10.62/0.10.63?slim=true)](https://docs.renovatebot.com/merge-confidence/) | ### GitHub Vulnerability Alerts #### [CVE-2024-27088](https://togithub.com/medikoo/es5-ext/security/advisories/GHSA-4gmj-3p3h-gm8h) ### Impact Passing functions with very long names or complex default argument names into `function#copy` or`function#toStringTokens` may put script to stall ### Patches Fixed with medikoo/es5-ext@3551cdd and medikoo/es5-ext@a52e957 Published with v0.10.63 ### Workarounds No real workaround aside of refraining from using above utilities. ### References [https://github.com/medikoo/es5-ext/issues/201](https://togithub.com/medikoo/es5-ext/issues/201) --- ### Release Notes <details> <summary>medikoo/es5-ext (es5-ext)</summary> ### [`v0.10.63`](https://togithub.com/medikoo/es5-ext/blob/HEAD/CHANGELOG.md#01063-2024-02-23) [Compare Source](https://togithub.com/medikoo/es5-ext/compare/v0.10.62...v0.10.63) </details> --- ### Configuration 📅 **Schedule**: Branch creation - "" in timezone Europe/Madrid, Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/Unleash/unleash). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yMTIuMCIsInVwZGF0ZWRJblZlciI6IjM3LjIxMi4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Test Environment:
Apple M1 macbook air, 2020 (ventura 13.3.1)
node module
name : es5-ext
node js
version : v18.16.0
2023_09_26
이동하 ( Lee Dong Ha of ZeroPointer Lab )
강성현 ( kang seonghyeun )
박성진 ( sungjin park )
김찬호 ( Chanho Kim )
이수영 ( Lee Su Young )
김민욱 ( MinUk Kim )
Team : For CVE
Subject : ReDoS_Vulnerability_Report_in_the_es5-ext_Module_copy.js_2023-09-26 011618.041116.txt
Dear es5-ext team,
I am writing to report a potential ReDoS (Regular Expression Denial of Service) vulnerability in your es5-ext module. It has come to my attention that the current regex implementation for parsing values in the module is susceptible to excessive backtracking, leading to potential DoS attacks.The regex implementation in question is as follows:
/^\sfunction\s([\0-')-\uffff]+)\s(([\0-(-\uffff]))\s*{/
This vulnerability can be exploited when there is an imbalance in parentheses, which results in excessive backtracking and subsequently increases the CPU load and processing time significantly. This vulnerability can be triggered using the following input:
'function{' + 'n'.repeat(31) + '){'
Here is a simple PoC code to demonstrate the issue:
const protocolre = /^\sfunction\s([\0-')-\uffff]+)\s(([\0-(-\uffff]))\s*{/;
const startTime = Date.now();
const maliciousInput = 'function{' + 'n'.repeat(31) + '){'
protocolre.test(maliciousInput);
const endTime = Date.now();
console.log("process time: ", endTime - startTime, "ms");
Modification adds a limit to the number of digits, thereby preventing the ReDoS vulnerability from occurring.
I believe it is crucial to address this issue promptly to ensure the security of your module for all users. Please let me know if you need any further information or assistance with this matter.
https://www.npmjs.com/package/es5-ext
The text was updated successfully, but these errors were encountered: