emerose (owner)

Revisions

gist: 215502 Download_button fork
public
Public Clone URL: git://gist.github.com/215502.git
Embed All Files: show embed
ruby-1.8.6.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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]
 
ruby-1.8.7.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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]
 
ruby-1.9.1.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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]
 
uri.parse.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 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