CVE-2013-1800: Permissions, Privileges, and Access Controls (CWE-264)
value: The crack gem 0.3.1 and earlier for Ruby does not properly restrict casts of string values, which might allow remote attackers to conduct object-injection attacks and execute arbitrary code, or cause a denial of service (memory and CPU consumption) by leveraging Action Pack support for (1) YAML type conversion or (2) Symbol type conversion, a similar vulnerability to CVE-2013-0156.
CWE description: Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.
Published: 2013-04-09T20:55Z
Repository: https://github.com/jnunemaker/crack
Language: Ruby
Files changed: lib/crack/xml.rb, test/xml_test.rb
Commit date: 2013-01-09 12:24:57 -0500
Commit message: Remove support for symbol and yaml.

Diff: diff --git a/lib/crack/xml.rb b/lib/crack/xml.rb
index b802200..df68d73 100644
--- a/lib/crack/xml.rb
+++ b/lib/crack/xml.rb
@@ -38,13 +38,11 @@ class REXMLUtilityNode #:nodoc:
   self.typecasts["date"]          = lambda{|v| v.nil? ? nil : Date.parse(v)}
   self.typecasts["dateTime"]      = lambda{|v| v.nil? ? nil : Time.parse(v).utc}
   self.typecasts["decimal"]       = lambda{|v| v.nil? ? nil : BigDecimal(v.to_s)}
   self.typecasts["double"]        = lambda{|v| v.nil? ? nil : v.to_f}
   self.typecasts["float"]         = lambda{|v| v.nil? ? nil : v.to_f}
-  self.typecasts["symbol"]        = lambda{|v| v.nil? ? nil : v.to_sym}
   self.typecasts["string"]        = lambda{|v| v.to_s}
-  self.typecasts["yaml"]          = lambda{|v| v.nil? ? nil : YAML.load(v)}
   self.typecasts["base64Binary"]  = lambda{|v| v.unpack('m').first }
 
   self.available_typecasts = self.typecasts.keys
 
   def initialize(name, normalized_attributes = {})
diff --git a/test/xml_test.rb b/test/xml_test.rb
index 5e2faf6..bfee13f 100644
--- a/test/xml_test.rb
+++ b/test/xml_test.rb
@@ -63,14 +63,14 @@ class XmlTest < Test::Unit::TestCase
           'login' => 'grep',
           'fullname' => 'Gary R Epstein'
         }
       }
     }
-    
+
     Crack::XML.parse(xml).should == hash
   end
-  
+
   context "Parsing xml with text and attributes" do
     setup do
       xml =<<-XML
         <opt>
           <user login="grep">Gary R Epstein</user>
@@ -88,24 +88,24 @@ class XmlTest < Test::Unit::TestCase
             'Simon T Tyson'
           ]
         }
       }
     end
-    
+
     should "be parse attributes for text node if present" do
       @data['opt']['user'][0].attributes.should == {'login' => 'grep'}
     end
-    
+
     should "default attributes to empty hash if not present" do
       @data['opt']['user'][1].attributes.should == {}
     end
-    
+
     should "add 'attributes' accessor methods to parsed instances of String" do
       @data['opt']['user'][0].respond_to?(:attributes).should be(true)
       @data['opt']['user'][0].respond_to?(:attributes=).should be(true)
     end
-    
+
     should "not add 'attributes' accessor methods to all instances of String" do
       "some-string".respond_to?(:attributes).should be(false)
       "some-string".respond_to?(:attributes=).should be(false)
     end
   end
@@ -147,11 +147,11 @@ class XmlTest < Test::Unit::TestCase
     xml_entities.each do |k,v|
       xml = "<tag>Some content #{v}</tag>"
       Crack::XML.parse(xml)['tag'].should =~ Regexp.new(k)
     end
   end
-  
+
   should "should unescape XML entities in attributes" do
     xml_entities.each do |k,v|
       xml = "<tag attr='Some content #{v}'></tag>"
       Crack::XML.parse(xml)['tag']['attr'].should =~ Regexp.new(k)
     end
@@ -224,22 +224,20 @@ class XmlTest < Test::Unit::TestCase
         <title></title>
         <id type="integer"></id>
         <approved type="boolean"></approved>
         <written-on type="date"></written-on>
         <viewed-at type="datetime"></viewed-at>
-        <content type="yaml"></content>
         <parent-id></parent-id>
       </topic>
     EOT
 
     expected_topic_hash = {
       'title'      => nil,
       'id'         => nil,
       'approved'   => nil,
       'written_on' => nil,
       'viewed_at'  => nil,
-      'content'    => nil,
       'parent_id'  => nil
     }
     Crack::XML.parse(topic_xml)["topic"].should == expected_topic_hash
   end
 
@@ -252,11 +250,10 @@ class XmlTest < Test::Unit::TestCase
         <approved type="boolean"> true </approved>
         <replies-count type="integer">0</replies-count>
         <replies-close-in type="integer">2592000000</replies-close-in>
         <written-on type="date">2003-07-16</written-on>
         <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
-        <content type="yaml">--- \n1: should be an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n  should_have_underscores: true\n</content>
         <author-email-address>david@loudthinking.com</author-email-address>
         <parent-id></parent-id>
         <ad-revenue type="decimal">1.5</ad-revenue>
         <optimum-viewing-angle type="float">135</optimum-viewing-angle>
         <resident type="symbol">yes</resident>
@@ -270,19 +267,15 @@ class XmlTest < Test::Unit::TestCase
       'approved' => true,
       'replies_count' => 0,
       'replies_close_in' => 2592000000,
       'written_on' => Date.new(2003, 7, 16),
       'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
-      # Changed this line where the key is :message.  The yaml specifies this as a symbol, and who am I to change what you specify
-      # The line in ActiveSupport is
-      # 'content' => { 'message' => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
-      'content' => { :message => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
       'author_email_address' => "david@loudthinking.com",
       'parent_id' => nil,
       'ad_revenue' => BigDecimal("1.50"),
       'optimum_viewing_angle' => 135.0,
-      'resident' => :yes
+      'resident' => 'yes',
     }
 
     Crack::XML.parse(topic_xml)["topic"].each do |k,v|
       v.should == expected_topic_hash[k]
     end
@@ -485,15 +478,15 @@ class XmlTest < Test::Unit::TestCase
       'pre_escaped_string' => 'First &amp; Last Name'
     }
 
     Crack::XML.parse(xml_string)['person'].should == expected_hash
   end
-  
+
   should "handle an empty xml string" do
     Crack::XML.parse('').should == {}
   end
-  
+
   # As returned in the response body by the unfuddle XML API when creating objects
   should "handle an xml string containing a single space" do
     Crack::XML.parse(' ').should == {}
   end
-end
\ No newline at end of file
+end

Vulnerable code:   self.typecasts["symbol"]        = lambda{|v| v.nil? ? nil : v.to_sym}
  self.typecasts["yaml"]          = lambda{|v| v.nil? ? nil : YAML.load(v)}
    
  
    
    
    
    
  
        <content type="yaml"></content>
      'content'    => nil,
        <content type="yaml">--- \n1: should be an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n  should_have_underscores: true\n</content>
      # Changed this line where the key is :message.  The yaml specifies this as a symbol, and who am I to change what you specify
      # The line in ActiveSupport is
      # 'content' => { 'message' => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
      'content' => { :message => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
      'resident' => :yes
  
  
end
Fixed code: 






      'resident' => 'yes',


end