In Ruby is there any way that data added to a string with interpolation can terminate the string? For example something like:

"This remains#{\somekindofmagic} and this does not" # => "This remains"

I'm assuming not but I want to be sure that doing something like

something.send("#{untrusted_input}=", more_untrusted_input)

doesn't actually leave some way that the interpolated string could be terminated and used to send eval.

有帮助吗?

解决方案

Not possible with input string data AFAIK. Ruby Strings can contain arbitrary binary data, there should be no magic combination of bytes that terminates a String early.

If you are worried about "injection" style attacks on Ruby strings, then this is generally not easy to achieve if input is in the form of external data that has been converted to a string (and your specific concern about having an eval triggered cannot occur). This style of attack relies on code that passes an input string into some other interpreter (e.g. SQL or JavaScript) without properly escaping language constructs.

However, if String parameters are coming in the form of Ruby objects from untrusted Ruby code in the same process, it is possible to add side-effects to them:

class BadString
  def to_s
    puts "Payload"
    "I am innocent"
  end
end

b = BadString.new

c = "Hello #{b}"
Payload
 => "Hello I am innocent"

Edit: Your example

something.send("#{untrusted_input}=", more_untrusted_input)

would still worry me slightly, if untrusted_input really is untrusted, you are relying heavily on the fact that there are no methods ending in = that you would be unhappy to have called. Sometimes new methods can be defined on core classes due to use of a framework or gem, and you may not know about them, or they may appear in later versions of a gem. Personally I would whitelist allowed method names for that reason, or use some other validation scheme on the incoming data, irrespective of how secure you feel against open-ended evals.

其他提示

Strings in ruby are internally handled as an array of bytes on the heap and an integer that holds the length of the string. So while in C a NUL byte (\0) terminates a string, this can not happen in ruby.

More info on ruby string internals here: http://patshaughnessy.net/2012/1/4/never-create-ruby-strings-longer-than-23-characters (also includes why ruby strings longer than 23 bytes were slower in ruby 1.9).

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top