Skip to content

Instantly share code, notes, and snippets.

@emerose
Created October 21, 2009 22:01
Show Gist options
  • Save emerose/215502 to your computer and use it in GitHub Desktop.
Save emerose/215502 to your computer and use it in GitHub Desktop.
irb(main):001:0> require 'cgi'
=> true
irb(main):002:0> require 'uri'
=> true
irb(main):003:0> RUBY_VERSION
=> "1.8.6"
irb(main):004:0> evil = "http://www.google.com%0A%60ls%0A%60"
=> "http://www.google.com%0A%60ls%0A%60"
irb(main):005:0> unescaped_evil = CGI::unescape(evil)
=> "http://www.google.com\n`ls\n`"
irb(main):006:0> uri = URI.parse(unescaped_evil)
=> #<URI::HTTP:0x3ff79afb7d28 URL:http://www.google.com>
irb(main):007:0> uri.to_s
=> "http://www.google.com" # totally safe
irb(main):008:0> URI.split(unescaped_evil)
=> ["http", nil, "www.google.com", nil, nil, "", nil, nil, nil]
irb(main):001:0> require 'cgi'
=> true
irb(main):002:0> require 'uri'
=> true
irb(main):003:0> RUBY_VERSION
=> "1.8.7"
irb(main):004:0> evil = "http://www.google.com%0A%60ls%0A%60"
=> "http://www.google.com%0A%60ls%0A%60"
irb(main):005:0> unescaped_evil = CGI::unescape(evil)
=> "http://www.google.com\n`ls\n`"
irb(main):006:0> uri = URI.parse(unescaped_evil)
=> #<URI::HTTP:0x1010a7a10 URL:http://www.google.com>
irb(main):007:0> uri.to_s
=> "http://www.google.com" # also totally safe
irb(main):008:0> URI.split(unescaped_evil)
=> ["http", nil, "www.google.com", nil, nil, "", nil, nil, nil]
irb(main):001:0> require 'uri'
=> true
irb(main):002:0> require 'cgi'
=> true
irb(main):003:0> RUBY_VERSION
=> "1.9.1"
irb(main):004:0> evil = "http://www.google.com%0A%60ls%0A%60"
=> "http://www.google.com%0A%60ls%0A%60"
irb(main):005:0> unescaped_evil = CGI::unescape(evil)
=> "http://www.google.com\n`ls\n`"
irb(main):006:0> uri = URI.parse(unescaped_evil)
=> #<URI::HTTP:0x0000010091c5f8 URL:http://www.google.com>
irb(main):007:0> uri.to_s
=> "http://www.google.com"
irb(main):008:0> URI.split(unescaped_evil)
=> ["http", nil, "www.google.com", nil, nil, "", nil, nil, nil]
# The URI.parse method calls URI.split as its first step -- and that method
# doesn't let the \n`ls\n` junk through into the final URI
def self.parse(uri)
scheme, userinfo, host, port,
registry, path, opaque, query, fragment = self.split(uri)
if scheme && @@schemes.include?(scheme.upcase)
@@schemes[scheme.upcase].new(scheme, userinfo, host, port,
registry, path, opaque, query,
fragment)
else
Generic.new(scheme, userinfo, host, port,
registry, path, opaque, query,
fragment)
end
end
# I suspect this is the reason why URI.parse doesn't throw an exception on
# unescaped_evil:
# (from URI::Parser's initialize_regexp in 1.9.1)
# for URI::split
ret[:ABS_URI] = Regexp.new('^' + pattern[:X_ABS_URI] + '$', Regexp::EXTENDED)
ret[:REL_URI] = Regexp.new('^' + pattern[:X_REL_URI] + '$', Regexp::EXTENDED)
# '$' in Ruby matches line breaks, not end-of-string. so the regexp in X_ABS_URI
# only matches what comes before the \n -- ie, only the safe part of the URI
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment