Skip to content

Instantly share code, notes, and snippets.

@movitto
Last active December 21, 2015 06:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save movitto/6261662 to your computer and use it in GitHub Desktop.
Save movitto/6261662 to your computer and use it in GitHub Desktop.
Workaround to security fix in rubygem-json commit #d0a62f3c fixing a situation which attacker could use the constant resolution mechanism in the json gem to subject the machine running it to a DoS attack. The fix involved disabling the conversion of json into ruby classes by default and recommending that the developer only enable it for validate…
require 'json'
class Class
class << self
attr_accessor :permitted_json_classes
end
def permit_json_create
Class.permitted_json_classes ||= []
unless Class.permitted_json_classes.include?(self.name)
Class.permitted_json_classes << self.name
end
end
end
def validate_json_hash(jh)
jh.each { |k,v|
if k == JSON.create_id &&
!Class.permitted_json_classes.include?(v)
raise ArgumentError, "can't create json class #{v}"
elsif v.is_a?(Hash)
parse_json_hash(jh)
end
}
end
def parse_json(js)
jp = JSON.parse js
return jp unless jp.is_a?(Hash)
validate_json_hash(jp)
JSON.parse js, :create_additions => true
end
class Foo
permit_json_create
def to_json(*a)
{'json_class' => self.class.to_s,
'data' => []}.to_json(*a)
end
def self.json_create(o)
new(*o['data'])
end
end
j = Foo.new.to_json
puts " #{j.class} #{j}"
f = parse_json(j)
puts " #{f.class} #{f}"
j2 = '{"json_class":"Fooz","data":[]}'
ns1 = Symbol.all_symbols.size
begin
parse_json(j2)
rescue => e
ns2 = Symbol.all_symbols.size
# replace the "parse_json(j2)" above with
# "JSON.parse(j2, :create_additions => true)"
# to see this change:
puts "#{e} #{ns1} #{ns2}"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment