Issue #5072 has been updated by Jeremy Evans.


Great.  I'll work on a patch that fixes the backwards compatibility issues mentioned in the 0002 patch (e.g. that instance_variable_defined?("foo") does not raise NameError).

Would you like this optimization ported to (class|instance)_variable_get, remove_(class|instance)_variable, remove_const, and (public_|)(instance_|)method?  I don't think those methods are as likely to be used with user-provided strings, but it may be desired to handle those for consistency.  I don't think send or const_get can use the optimization, since if the method or constant does not exist, they need to provide the symbol to method_missing or const_missing.
----------------------------------------
Feature #5072: Avoid inadvertent symbol creation in reflection methods
http://redmine.ruby-lang.org/issues/5072

Author: Jeremy Evans
Status: Open
Priority: Normal
Assignee: 
Category: core
Target version: 


I recently discovered a denial of service vulnerability in ActiveRecord's mass assignment methods related to the insecure use of ruby's reflection methods (e.g. respond_to?).  Because these methods take strings and automatically create symbols from them, they are not safe to call with a string coming from the user.  Because they create the symbol internally, they look safe, but if you pass user-created strings to these methods, you open yourself up to denial of service through memory exhaustion (see http://sequel.heroku.com/2011/07/16/dangerous-reflection/).

This could be fixed using a fairly simple observation, which is that if you do:

  respond_to?("foo")

and "foo" is not already in the symbol table, no method named "foo" can exist.  So this code provides a patch that changes the reflection methods to return false immediately if given a string which doesn't already exist in the symbol table.  There should be no performance impact from this, since the symbol table lookup has to be done anyway.

I'm also adding an earlier patch I wrote that adds String#interned?, for checking if a string is already interned.  There was an internal method for this added in r10932, but it must have been removed while the prototype was left in intern.h.  String#interned? allows a user to check if a string is already in the symbol table, and can be used by user code to ensure that symbols are not created inadvertently.


-- 
http://redmine.ruby-lang.org