<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Programming Evolved</title>
  <link href="http://programmingevolved.com/atom.xml" rel="self"/>
  <link href="http://programmingevolved.com/"/>
  <updated>2013-02-19T10:58:45+11:00</updated>
  <id>http://programmingevolved.com/</id>
  <author>
    <name>David Miani</name>
    
  </author>

  
  <entry>
    <title>Data Serialization is different to Data Transfer!</title>
    <link href="http://programmingevolved.com/blog/2013/02/17/data-serialization-is-different-to-data-transfer/"/>
    <updated>2013-02-17T22:59:00+11:00</updated>
    <id>http://programmingevolved.com/blog/2013/02/17/data-serialization-is-different-to-data-transfer</id>
    <content type="html">&lt;p&gt;Nearly everyone at this stage has heard about the huge rails vulnerabilities that were discovered this month. However, there is a lot of confusion and misinformation on the net about it, and what the primary causes of them were. So here is a complete guide to what caused the bugs, and why I think not understanding the difference between data serialization and data transfer (or more precisely, data interchange) was the root cause of the security issues.&lt;/p&gt;

&lt;!&#8211; more &#8211;&gt;


&lt;h1&gt;Basic setup&lt;/h1&gt;

&lt;p&gt;For all the examples in this post, I ran them with ruby 1.9.3 with the Gemfile:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;
source &amp;quot;http://rubygems.org&amp;quot;
gem &amp;#x27;activesupport&amp;#x27;, &amp;#x27;3.2.9&amp;#x27;
gem &amp;#x27;builder&amp;#x27;, &amp;#x27;3.1.4&amp;#x27; # needed for to_xml
gem &amp;#x27;json&amp;#x27;, &amp;#x27;1.7.6&amp;#x27;
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;This basically defines what versions of libraries will be running when I run the examples. I chose 3.2.9 for the &lt;code&gt;activesupport&lt;/code&gt; library as that is the newest version containing the bug, and 1.7.6 of &lt;code&gt;json&lt;/code&gt; for the same reason.&lt;/p&gt;

&lt;p&gt;There are two key factors in yaml bug: the &lt;code&gt;from_xml&lt;/code&gt; method in the &lt;code&gt;activesupport&lt;/code&gt; library, and what YAML is and should do.&lt;/p&gt;

&lt;h1&gt;Active Support&lt;/h1&gt;

&lt;p&gt;Rails has a sub library known as &lt;code&gt;activesupport&lt;/code&gt;. This is a library that isn&#8217;t strictly to do with rails, but instead supplies a lot of additional methods for core ruby classes. For example:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;?&amp;gt; require &amp;#x27;active_support/core_ext&amp;#x27;
=&amp;gt; true
&amp;gt;&amp;gt; 16.hours
=&amp;gt; 57600 seconds
&amp;gt;&amp;gt; &amp;quot;&amp;quot;.blank?
=&amp;gt; true
&amp;gt;&amp;gt; 3.in? [1,2,3,4]
=&amp;gt; true
&amp;gt;&amp;gt; &amp;#x27;alice in wonderland&amp;#x27;.titleize
=&amp;gt; &amp;quot;Alice In Wonderland&amp;quot;
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;This can be used in any ruby project, and is very useful even in non-rails apps.&lt;/p&gt;

&lt;p&gt;Two more useful methods are the &lt;code&gt;from_xml&lt;/code&gt; and &lt;code&gt;to_xml&lt;/code&gt; methods. They convert an xml string into a &lt;code&gt;Hash&lt;/code&gt; object, and vice versa, eg:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;Hash.from_xml(&amp;#x27;&amp;lt;person&amp;gt;&amp;lt;name&amp;gt;Fred&amp;lt;/name&amp;gt;&amp;lt;age&amp;gt;34&amp;lt;/age&amp;gt;&amp;lt;/person&amp;gt;&amp;#x27;)
=&amp;gt; {&amp;quot;person&amp;quot;=&amp;gt;{&amp;quot;name&amp;quot;=&amp;gt;&amp;quot;Fred&amp;quot;, &amp;quot;age&amp;quot;=&amp;gt;&amp;quot;34&amp;quot;}}
&amp;gt;&amp;gt; puts({ &amp;#x27;x&amp;#x27; =&amp;gt; &amp;#x27;hello&amp;#x27;, &amp;#x27;y&amp;#x27; =&amp;gt; &amp;#x27;goodbye&amp;#x27; }.to_xml)
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;hash&amp;gt;
  &amp;lt;x&amp;gt;hello&amp;lt;/x&amp;gt;
  &amp;lt;y&amp;gt;goodbye&amp;lt;/y&amp;gt;
&amp;lt;/hash&amp;gt;
=&amp;gt; nil
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;Their behaviour is very obvious when working with strings. They can also work with other types as well:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;hash = { number: 34, array: [1,2,3, &amp;quot;str&amp;quot;], inner_h: { &amp;quot;x&amp;quot; =&amp;gt; 3 } }
=&amp;gt; {:number=&amp;gt;34, :array=&amp;gt;[1, 2, 3, &amp;quot;str&amp;quot;], :inner_h=&amp;gt;{&amp;quot;x&amp;quot;=&amp;gt;3}}
&amp;gt;&amp;gt; puts(hash.to_xml)
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;hash&amp;gt;
  &amp;lt;number type=&amp;quot;integer&amp;quot;&amp;gt;34&amp;lt;/number&amp;gt;
  &amp;lt;array type=&amp;quot;array&amp;quot;&amp;gt;
    &amp;lt;array type=&amp;quot;integer&amp;quot;&amp;gt;1&amp;lt;/array&amp;gt;
    &amp;lt;array type=&amp;quot;integer&amp;quot;&amp;gt;2&amp;lt;/array&amp;gt;
    &amp;lt;array type=&amp;quot;integer&amp;quot;&amp;gt;3&amp;lt;/array&amp;gt;
    &amp;lt;array&amp;gt;str&amp;lt;/array&amp;gt;
  &amp;lt;/array&amp;gt;
  &amp;lt;inner-h&amp;gt;
    &amp;lt;x type=&amp;quot;integer&amp;quot;&amp;gt;3&amp;lt;/x&amp;gt;
  &amp;lt;/inner-h&amp;gt;
&amp;lt;/hash&amp;gt;
=&amp;gt; nil
&amp;gt;&amp;gt; Hash.from_xml(hash.to_xml)
=&amp;gt; {&amp;quot;hash&amp;quot;=&amp;gt;{&amp;quot;number&amp;quot;=&amp;gt;34, &amp;quot;array&amp;quot;=&amp;gt;[1, 2, 3, &amp;quot;str&amp;quot;], &amp;quot;inner_h&amp;quot;=&amp;gt;{&amp;quot;x&amp;quot;=&amp;gt;3}}}
&amp;gt;&amp;gt; Hash.from_xml(hash.to_xml)[&amp;quot;hash&amp;quot;] == hash.stringify_keys
=&amp;gt; true
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;Note how the xml elements are given a &lt;code&gt;type=&quot;&amp;lt;type&amp;gt;&quot;&lt;/code&gt; attribute. This is used by &lt;code&gt;from_xml&lt;/code&gt; to parse the objects back to the original type. The only change is symbol keys became strings. This is fixed with &lt;code&gt;stringify_keys&lt;/code&gt;, allowing a round trip conversion using simple types.&lt;/p&gt;

&lt;h1&gt;YAML&lt;/h1&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.yaml.org/&quot;&gt;YAML website&lt;/a&gt;, describes YAML as:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&#8230; a human friendly data serialization standard for all programming languages.&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;It is useful to compare that to the definition given for json from &lt;a href=&quot;http://www.json.org/&quot;&gt;its website&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;JSON (JavaScript Object Notation) is a lightweight data-interchange format.&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;While they seem similar, there is a big difference between data interchange and data serialization. Data exchange just means to pass information from one place to another. Data serialization however involves converting data into a format that can be saved or transferred, and then be transferred back into the original data through deserialization. Ruby has both json and YAML libraries, so the differences between between the two can be easily show.&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;?&amp;gt; require &amp;#x27;json&amp;#x27;
=&amp;gt; true
&amp;gt;&amp;gt; hash = { x: 34, y: &amp;quot;hello&amp;quot; }
=&amp;gt; {:x=&amp;gt;34, :y=&amp;gt;&amp;quot;hello&amp;quot;}
&amp;gt;&amp;gt; puts hash.to_json
{&amp;quot;x&amp;quot;:34,&amp;quot;y&amp;quot;:&amp;quot;hello&amp;quot;}
=&amp;gt; nil
&amp;gt;&amp;gt; JSON::parse(hash.to_json)
=&amp;gt; {&amp;quot;x&amp;quot;=&amp;gt;34, &amp;quot;y&amp;quot;=&amp;gt;&amp;quot;hello&amp;quot;}
&amp;gt;&amp;gt; JSON::parse(hash.to_json) == hash
=&amp;gt; false
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;JSON, being a data transfer protocol, doesn&#8217;t concern itself with being able to deserialize the output back to the original object. Even with the simple example of &lt;code&gt;{ x: 34, y: &quot;hello&quot;}&lt;/code&gt;, it can&#8217;t complete a round trip conversion, since the json spec has no reference of symbols, and therefore just converts them to strings.&lt;/p&gt;

&lt;p&gt;This isn&#8217;t a bad thing for a data transfer format - in fact it makes the spec very simple. One of the reasons json is taking over/has taken over xml as a data transfer format is for this reason. It is easy to create and consume by any language as it only has a small number of primitives.&lt;/p&gt;

&lt;p&gt;YAML, on the other hand, does focus on data serialization, and can complete the round trip:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;require &amp;#x27;yaml&amp;#x27;
=&amp;gt; false
&amp;gt;&amp;gt; puts hash.to_yaml
&#8212;
:x: 34
:y: hello
=&amp;gt; nil
&amp;gt;&amp;gt; YAML::load(hash.to_yaml)
=&amp;gt; {:x=&amp;gt;34, :y=&amp;gt;&amp;quot;hello&amp;quot;}
&amp;gt;&amp;gt; YAML::load(hash.to_yaml) == hash
=&amp;gt; true
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;But it is not just hashes that can be serialized by YAML, almost anything can. For example, using the definitions from this file:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;
class Person
  attr_accessor :name, :age
  
  def ==(other)
    name == other.name &amp;amp;&amp;amp; age == other.age
  end
end

class Organization 
  attr_accessor :employees, :boss
  def ==(other)
    employees == other.employees &amp;amp;&amp;amp; boss == other.boss
  end
end

class CustomHash &amp;lt; Hash

end

# make some global objects for testing
$person = Person.new
$person.age = 34
$person.name = &amp;quot;Fred&amp;quot;

$person2 = Person.new
$person2.age = 50
$person2.name = &amp;#x27;Sarah&amp;#x27;

$boss = Person.new
$boss.age = 60
$boss.name = &amp;#x27;Bill&amp;#x27;

$organization = Organization.new
$organization.employees = [$person, $person2]
$organization.boss = $boss

$hash = CustomHash.new
$hash[&amp;#x27;organization&amp;#x27;] = $organization
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;YAML can do the following:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;load &amp;#x27;definitions.rb&amp;#x27;
=&amp;gt; true
&amp;gt;&amp;gt; puts $person.to_yaml
&#8212; !ruby/object:Person
age: 34
name: Fred
=&amp;gt; nil
&amp;gt;&amp;gt; YAML::load($person.to_yaml) == $person
=&amp;gt; true
&amp;gt;&amp;gt; puts $organization.to_yaml
&#8212; !ruby/object:Organization
employees:
- !ruby/object:Person
  age: 34
  name: Fred
- !ruby/object:Person
  age: 50
  name: Sarah
boss: !ruby/object:Person
  age: 60
  name: Bill
=&amp;gt; nil
&amp;gt;&amp;gt; YAML::load($organization.to_yaml) == $organization
=&amp;gt; true
&amp;gt;&amp;gt; puts $hash.to_yaml
&#8212; !ruby/hash:CustomHash
organization: !ruby/object:Organization
  employees:
  - !ruby/object:Person
    age: 34
    name: Fred
  - !ruby/object:Person
    age: 50
    name: Sarah
  boss: !ruby/object:Person
    age: 60
    name: Bill
=&amp;gt; nil
&amp;gt;&amp;gt; YAML::load($hash.to_yaml) == $hash
=&amp;gt; true
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;Note how:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The output for the serialization is very clear&lt;/li&gt;
&lt;li&gt;YAML successfully recovered the original objects through deserialization (using the &lt;code&gt;YAML::load&lt;/code&gt; method)&lt;/li&gt;
&lt;li&gt;The output is very ruby specific&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This makes YAML quite a nice serialization format, due to the first two points, but a poor transfer format, due to the third point. The story about using YAML as a transfer format gets a lot worse though&#8230;&lt;/p&gt;

&lt;h1&gt;How does YAML deserialize objects??&lt;/h1&gt;

&lt;p&gt;You may be wondering how yaml was successfully able to rebuild the original objects. It is actually very simple - when it encounters a &lt;code&gt;!ruby/object:&amp;lt;class&amp;gt;&lt;/code&gt; section, for each attribute in that section it sets an instance variable on that object to the given value. For example, with:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;
&#8212; !ruby/object:Person
name: Fred
age: 34
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;The YAML library effectively runs:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;
result = Person.new
result.instance_variable_set(:@name, &amp;#x27;Fred&amp;#x27;)
result.instance_variable_set(:@age, 34)
return result
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;A special case is working with subclasses of &lt;code&gt;Hash&lt;/code&gt;, like &lt;code&gt;CustomHash&lt;/code&gt; from above. In that case, it calls &lt;code&gt;[]&lt;/code&gt; for each attribute. Given:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;
&#8212; !ruby/Hash:CustomHash
value: 34
x: &amp;quot;hello&amp;quot;
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;The following will be run when deserializing it.&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;
result = CustomHash.new
result[&amp;#x27;value&amp;#x27;] = 34
result[&amp;#x27;x&amp;#x27;] = &amp;quot;hello&amp;quot;
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;These two features however open up huge security holes if you parse YAML from an untrusted source - it would allow an attacker to run any &lt;code&gt;[]=&lt;/code&gt; method on any class in your system, as well as create any object with any instance instance variables!&lt;/p&gt;

&lt;p&gt;For example, if you had the following class in your system:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;
# stores an action on a target with parameters. When methods are called on this
# object, evaluates the action, and calls the code on that.
class LazyObject
  def initialize(target, action, arguments)
    @target, @action, @arguments = target, action, arguments
  end
  
  def method_missing(method, *args)
    @result = @target.send(@action, *@arguments) if @result.nil?
    @result.send(method, *args)
  end
end
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;With the given YAML code:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;
&#8212; !ruby/object:LazyObject
target: Kernel
action: eval
arguments: [&amp;quot;File.write(&amp;#x27;hacked.txt&amp;#x27;, &amp;#x27;you are compromised!!!&amp;#x27;)&amp;quot;]
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;You can now execute arbitrary code, if the original code called any method on the result of the parse&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;load &amp;#x27;lazy_object.rb&amp;#x27;
=&amp;gt; true
&amp;gt;&amp;gt; result = YAML::load_file(&amp;#x27;dangerous.yaml&amp;#x27;)
=&amp;gt; #&amp;lt;LazyObject:0x007fe7390a5488 @target=&amp;quot;Kernel&amp;quot;, @action=&amp;quot;eval&amp;quot;, @arguments=[&amp;quot;File.write(&amp;#x27;hacked.txt&amp;#x27;, &amp;#x27;you are compromised!!!&amp;#x27;)&amp;quot;]&amp;gt;
&amp;gt;&amp;gt; puts result.length # assuming we were expecting an array, we may call length on it. 
NoMethodError: undefined method `length&amp;#x27; for 22:Fixnum
    from lazy_object.rb:11:in `method_missing&amp;#x27;
    from (irb):20
    from /Users/david/.rvm/rubies/ruby-1.9.3-p125/bin/irb:16:in `&amp;lt;main&amp;gt;&amp;#x27;
&amp;gt;&amp;gt; File.read(&amp;#x27;hacked.txt&amp;#x27;)
=&amp;gt; &amp;quot;you are compromised!!!&amp;quot;
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;The scary part of this is there wasn&#8217;t any call to &lt;code&gt;eval&lt;/code&gt; in the original system - it is just that the eval call could be triggered by initializing &lt;code&gt;LazyObject&lt;/code&gt; with the right instance variables. &lt;code&gt;LazyObject&lt;/code&gt; isn&#8217;t inherently insecure, it is just that if an attacker can create objects at will, many original safe constructs suddenly become unsafe.&lt;/p&gt;

&lt;p&gt;This isn&#8217;t the only issue with using YAML with untrusted input. See the &lt;a href=&quot;http://tenderlovemaking.com/2013/02/06/yaml-f7u12.html&quot;&gt;post by Aaron Patterson&lt;/a&gt; for a lot more detail. In short, unless you prevent anything other than a few core types (eg ints, strings, bools, arrays and hashes) to be serialized, YAML isn&#8217;t safe with untrusted input.&lt;/p&gt;

&lt;p&gt;Now this isn&#8217;t very surprising when you consider YAML as a data serialization format - it is no different &lt;a href=&quot;http://docs.python.org/2/library/pickle.html#module-pickle&quot;&gt;pickling in python&lt;/a&gt; or &lt;a href=&quot;http://www.ruby-doc.org/core-1.9.3/Marshal.html&quot;&gt;marshaling in ruby&lt;/a&gt; - neither should be used with unsafe input. Serialization security flaws have even &lt;a href=&quot;http://tyranidslair.blogspot.com.au/2013/02/fun-with-java-serialization-and.html&quot;&gt;been found in java&lt;/a&gt;. The only serialization library I would trust with untrusted input would be haskell&#8217;s &lt;a href=&quot;http://hackage.haskell.org/packages/archive/binary/0.4.1/doc/html/Data-Binary.html&quot;&gt;Data.Binary&lt;/a&gt; library - by definition of its types, and the fact that there is no reflection, the only thing you can get back from deserialization with &lt;code&gt;Data.Binary&lt;/code&gt; is what you expect, or an error.&lt;/p&gt;

&lt;p&gt;Unfortunately, this property of YAML isn&#8217;t advertised very well, so many people are unaware of this. Including one rails contributer 6 years ago&#8230;&lt;/p&gt;

&lt;h1&gt;YAML and from_xml&lt;/h1&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/rails/rails/commit/27ba5edef1c4264a8d1c0e54675723d37a391dd8#L5R133&quot;&gt;commit in question&lt;/a&gt; added a new &#8216;feature&#8217; to &lt;code&gt;from_xml&lt;/code&gt; - it allowed the type of a xml field to also be &lt;code&gt;yaml&lt;/code&gt;. For example:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;require &amp;#x27;active_support/core_ext&amp;#x27;
=&amp;gt; true
&amp;gt;&amp;gt; xml = &amp;lt;&amp;lt;eof
&amp;lt;field type=&amp;quot;yaml&amp;quot;&amp;gt;
#{$boss.to_yaml}
&amp;lt;/field&amp;gt;
eof
=&amp;gt; &amp;quot;&amp;lt;field type=\&amp;quot;yaml\&amp;quot;&amp;gt;\n&#8212; !ruby/object:Person\nage: 60\nname: Bill\n\n&amp;lt;/field&amp;gt;\n&amp;quot;
&amp;gt;&amp;gt; data = Hash.from_xml(xml)
=&amp;gt; {&amp;quot;field&amp;quot;=&amp;gt;#&amp;lt;Person:0x007fe739043468 @age=60, @name=&amp;quot;Bill&amp;quot;&amp;gt;}
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;And now the &lt;code&gt;from_xml&lt;/code&gt; method is completely insecure, for all the reasons described above. The &lt;code&gt;from_xml&lt;/code&gt; method is used by rails in parameter parsing when parameters are passed via xml. This vulnerability allowed attackers to remotely execute code by passing an appropriate xml value containing yaml to a rails application.&lt;/p&gt;

&lt;h1&gt;JSON and deserialization&lt;/h1&gt;

&lt;p&gt;There was another serious security flaw that was also caused by not understanding the security problems unrestricted deserialization can cause.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;json&lt;/code&gt; gem has a &quot;feature&quot; whereby with certain inputs, it would deserialize to an object. For example if the following class existed:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;
class Hero
  attr_accessor :name, :level
  def self.json_create(attributes) 
    result = self.new
    result.name = attributes[&amp;quot;name&amp;quot;]
    result.level = attributes[&amp;quot;level&amp;quot;]
    result
  end
end
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;We can now create the class by using the special key &lt;code&gt;&quot;json_class&quot;&lt;/code&gt;:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;?&amp;gt; load &amp;#x27;Hero.rb&amp;#x27;
=&amp;gt; true
&amp;gt;&amp;gt; require &amp;#x27;json&amp;#x27;
=&amp;gt; true
&amp;gt;&amp;gt; JSON.parse &amp;#x27;{ &amp;quot;json_class&amp;quot;:&amp;quot;Hero&amp;quot;, &amp;quot;name&amp;quot;:&amp;quot;Superman&amp;quot;, &amp;quot;level&amp;quot;:10 }&amp;#x27;
=&amp;gt; #&amp;lt;Hero:0x007fd97515c2e0 @name=&amp;quot;Superman&amp;quot;, @level=10&amp;gt;
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;We once again have object creation from a data transfer format, and can create any object that implements the &lt;code&gt;json_create&lt;/code&gt; class method. There are no classes in rails that use this feature. However, the &lt;code&gt;json&lt;/code&gt; gem comes bundled with the &lt;code&gt;JSON::GenericObject&lt;/code&gt; class. This object works like javascript objects do: you can set attributes with &lt;code&gt;obj.val = &quot;something&quot;&lt;/code&gt;, and retrieve them with &lt;code&gt;obj.val&lt;/code&gt;:&lt;/p&gt;

&lt;div&gt;
&lt;code&gt;&lt;pre&gt;obj = JSON::GenericObject.new
=&amp;gt; #&amp;lt;JSON::GenericObject&amp;gt;
&amp;gt;&amp;gt; obj.val = 34
=&amp;gt; 34
&amp;gt;&amp;gt; puts obj.val
34
=&amp;gt; nil
&amp;gt;&amp;gt; obj.trusted_input = true
=&amp;gt; true
&amp;gt;&amp;gt; puts obj.trusted_input
true
=&amp;gt; nil
&lt;/pre&gt;&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;Unfortunately, this allows us, with the powers of duck typing, to pretend to be another object, and return what we want from methods call by the code that is using the parsed json. This allowed sql injection to occur with rails. The discoverer of this bug made an &lt;a href=&quot;http://www.zweitag.de/en/blog/ruby-on-rails-vulnerable-to-mass-assignment-and-sql-injection&quot;&gt;excellent blog post&lt;/a&gt; about it.&lt;/p&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Many things have been said about the wave of security flaws that have hit rails over the last month. I believe the key issue is not understanding the difference, and security trade-offs between data transfer and data serialization. The bug with the json library came from it pretending to be a serialization library. The bug in activesupport came from using yaml in a place where untrusted data was not only possible, but the norm. Unless a data serialization library has been made explicitly to also be used with untrusted data, it shouldn&#8217;t be used with it.&lt;/p&gt;
</content>
  </entry>
  
</feed>
