Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge rexml-expansion-fix gem into activesupport.

  • Loading branch information...
commit ebfa43c423ac16bb699424d8d3db11855dd79a91 1 parent 76797b4
@NZKoz NZKoz authored
View
35 activesupport/lib/active_support/core_ext/rexml.rb
@@ -0,0 +1,35 @@
+require 'rexml/document'
+require 'rexml/entity'
+
+# Fixes the rexml vulnerability disclosed at:
+# http://www.ruby-lang.org/en/news/2008/08/23/dos-vulnerability-in-rexml/
+# This fix is identical to rexml-expansion-fix version 1.0.1
+
+unless REXML::VERSION > "3.1.7.2"
+ module REXML
+ class Entity < Child
+ undef_method :unnormalized
+ def unnormalized
+ document.record_entity_expansion! if document
+ v = value()
+ return nil if v.nil?
+ @unnormalized = Text::unnormalize(v, parent)
+ @unnormalized
+ end
+ end
+ class Document < Element
+ @@entity_expansion_limit = 10_000
+ def self.entity_expansion_limit= val
+ @@entity_expansion_limit = val
+ end
+
+ def record_entity_expansion!
+ @number_of_expansions ||= 0
+ @number_of_expansions += 1
+ if @number_of_expansions > @@entity_expansion_limit
+ raise "Number of entity expansions exceeded, processing aborted."
+ end
+ end
+ end
+ end
+end
View
21 activesupport/test/core_ext/hash_ext_test.rb
@@ -839,6 +839,27 @@ def test_array_values_are_not_sorted
:person => {:id => [20, 10]}
end
+ def test_expansion_count_is_limited
+ assert_raises RuntimeError do
+ attack_xml = <<-EOT
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE member [
+ <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
+ <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
+ <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
+ <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
+ <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
+ <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
+ <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
+ ]>
+ <member>
+ &a;
+ </member>
+ EOT
+ Hash.from_xml(attack_xml)
+ end
+ end
+
private
def assert_query_equal(expected, actual, message = nil)
assert_equal expected.split('&'), actual.to_query.split('&')
Please sign in to comment.
Something went wrong with that request. Please try again.