cheroot icon indicating copy to clipboard operation
cheroot copied to clipboard

Host header is not validated

Open kasium opened this issue 1 year ago • 9 comments

I'm submitting a ...

  • [X] 🐞 bug report
  • [ ] 🐣 feature request
  • [ ] ❓ question about the decisions made in the repository

🐞 Describe the bug. What is the current behavior? An invalid host header which does not conform idna is just passed to the underlying wsgi application w/o any validation

What is the motivation / use case for changing the behavior? If the host header contains invalid data, this this data is passed as the HTTP_HOST environment field. It can lead to various issues

💡 To Reproduce Code

from flask import Flask
from cheroot.wsgi import Server

app = Flask(__name__)
server = Server(bind_addr=("localhost", 5001), wsgi_app=app)
server.safe_start()

Now send a request to the server where you set the Host header field to foobar/...

💡 Expected behavior Cheroot declines requests with invalid host header field.

📋 Environment

  • Cheroot version: 10.0.0
  • Python version: 3.12.0
  • OS: Linux

📋 Additional context This was already reported to flask https://github.com/pallets/flask/issues/5392

kasium avatar Feb 09 '24 15:02 kasium

Thanks! It'd be useful to know if h11 has this problem so we'd know if #201 would address this problem.

webknjaz avatar Feb 13 '24 00:02 webknjaz

@kasium would something like this be a smaller repro?

from cheroot.wsgi import Server, PathInfoDispatcher

Server(bind_addr=("localhost", 5001), wsgi_app=PathInfoDispatcher({})).safe_start()

webknjaz avatar Feb 13 '24 00:02 webknjaz

@webknjaz this does not show the issue for me

kasium avatar Feb 13 '24 13:02 kasium

@kasium are you saying that it's Flask that crashes when it sees something it doesn't expect?

It could be useful to get a PR with test cases for valid and invalid values of the header.

webknjaz avatar Feb 13 '24 21:02 webknjaz

Yes, flask assumes that the Header was validated before but it's not. A valid header is something like localhost:1234, an invalid one foobar/..

kasium avatar Feb 15 '24 11:02 kasium

@kasium would you mind composing a pull request with an acceptance/regression test for this? It'd be useful to merge it in even without an implementation (marked with xfail).

webknjaz avatar Mar 18 '24 15:03 webknjaz

Sure, let me have a look later this week

kasium avatar Mar 18 '24 15:03 kasium

@webknjaz to write a test I need to know where a validation would happen. Also the error does only occur if e.g. a wsgi app parses the header later down the stack.

I checked the cheroot code further and I think the best place for such a validation would be HTTPRequest.read_request_headers. To keep compatibility, the server could accept a new flag which turns validation on. If the header is not valid, it could then answer with 400 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host). What do you think?

kasium avatar Mar 19 '24 17:03 kasium

Just wondering if this would help? https://github.com/cherrypy/cheroot/pull/722

rockystone77 avatar Jul 01 '24 04:07 rockystone77