From b48ff03347a6d46e8dc674e242ce74c6381962a5 Mon Sep 17 00:00:00 2001 From: Security Curious Date: Fri, 2 Jul 2021 15:30:02 -0400 Subject: [PATCH] Prevent ReDOS vuln on URI Template matching The regular expression used to match a template against a URL is vulnerable to a regular expression denial-of-service via catastrophic backtracking. This commit includes a test that demonstrates the failure without the fix as well as updates the regexp to remove the vulnerability. The vulnerability is removed by updating the grouping to be atomic. --- lib/addressable/template.rb | 2 +- spec/addressable/template_spec.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/addressable/template.rb b/lib/addressable/template.rb index 2696695..45967ce 100644 --- a/lib/addressable/template.rb +++ b/lib/addressable/template.rb @@ -37,7 +37,7 @@ class Template Addressable::URI::CharacterClasses::DIGIT + '_' var_char = - "(?:(?:[#{variable_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)" + "(?>(?:[#{variable_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)" RESERVED = "(?:[#{anything}]|%[a-fA-F0-9][a-fA-F0-9])" UNRESERVED = diff --git a/spec/addressable/template_spec.rb b/spec/addressable/template_spec.rb index a019165..d47589a 100644 --- a/spec/addressable/template_spec.rb +++ b/spec/addressable/template_spec.rb @@ -19,6 +19,7 @@ require "spec_helper" require "bigdecimal" +require "timeout" require "addressable/template" shared_examples_for 'expands' do |tests| @@ -1340,6 +1341,14 @@ def self.match(name) expect(subject).not_to match("foo_bar*") expect(subject).not_to match("foo_bar:20") end + + it 'should parse in a reasonable time' do + expect do + Timeout.timeout(0.1) do + expect(subject).not_to match("0"*25 + "!") + end + end.not_to raise_error + end end context "VARIABLE_LIST" do subject { Addressable::Template::VARIABLE_LIST }