jnunemaker / httparty

:tada: Makes http fun again!
MIT License
5.82k stars 963 forks source link

HTTParty cannot follow redirects with relative paths containing ".." #582

Open vaneyckt opened 6 years ago

vaneyckt commented 6 years ago

Hey all,

given a webserver that has an endpoint of the form <my_url>/foo/bar/ that redirects to <my_url>/foo/bar using a relative redirect containing "..", we notice that this redirect cannot be followed.

For example, imagine that /foo/bar/ responds with

< HTTP/1.1 301
< X-Frame-Options: SAMEORIGIN
< Location: ../bar
< Set-Cookie: wd-alt-sessionid=; Path=/; Secure; HttpOnly
< Content-Length: 0
< Date: Thu, 15 Mar 2018 09:55:03 GMT
< ...

then HTTParty will throw a 404 when trying to redirect.

require 'httparty'

HTTParty.get('http://localhost:4567/foo/bar/').response.code
=> 404

Note that this redirect is successfully handled by both curl and Python's request library. Section 5.2.4 2A of the RFC also states that this is valid.

jmahoney commented 4 years ago

I've tried replicating this with a simple sinatra app and HTTParty seems to work fine.

code:

require 'sinatra'

get '/landing_service.html' do
  return "Service Response"
end

get '/landing/service' do
  headers['Location'] = '../landing_service.html'
  status 301
end

verbose curl output

curl -v http://localhost:4567/landing/service
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4567 (#0)
> GET /landing/service HTTP/1.1
> Host: localhost:4567
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Content-Type: text/html;charset=utf-8
< Location: ../landing_service.html
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< Content-Length: 0
<
* Connection #0 to host localhost left intact

httparty output

irb(main):002:0> HTTParty.get('http://localhost:4567/landing/service').response.code
=> "200"

That said, there's an incomplete cucumber test that I'd like to flesh out if it's helpful?

jmahoney commented 4 years ago

I've learned a bit more by working on the cucumber test

When httparty is pointed at /foo/bar and is redirected to ../foo.html it will make a request to /foo/../foo.html.

Puma/Sinatra treats that the same as /foo.html and returns a 200

Mongrel, at least as it's set up in the tests, doesn't match the url and throws a 404.

Curl sorts out the path before making the request and calls /foo.html when it gets the redirect.

That seems like the correct behaviour to me.

Thoughts?