abhinavsingh / proxy.py

💫 Ngrok FRP Alternative • ⚡ Fast • 🪶 Lightweight • 0️⃣ Dependency • 🔌 Pluggable • 😈 TLS interception • 🔒 DNS-over-HTTPS • 🔥 Poor Man's VPN • ⏪ Reverse & ⏩ Forward • 👮🏿 "Proxy Server" framework • 🌐 "Web Server" framework • ➵ ➶ ➷ ➠ "PubSub" framework • 👷 "Work" acceptor & executor framework
https://abhinavsingh.com/proxy-py-a-lightweight-single-file-http-proxy-server-in-python/
BSD 3-Clause "New" or "Revised" License
2.92k stars 569 forks source link

Security: Bypass proxy authentication with HTTP/1.0 requests #1267

Closed larsks closed 2 months ago

larsks commented 1 year ago

Describe the bug

It is possible to bypass proxy authentication by sending an HTTP/1.0 request with no request headers.

To Reproduce Steps to reproduce the behavior:

  1. Run proxy.py as proxy --basic-auth user:secret
  2. Run the following Python code:

    import requests
    
    proxies = {
      "http": "http://127.0.0.1:8899",
      "https": "http://127.0.0.1:8899"
    }
    
    response = requests.get("https://www.example.com", proxies=proxies)
    
    print(response.status_code) 
  3. See that the proxy accepts the request and returns the remote content.

You can reproduce this yourself like this:

$ telnet localhost 8899
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
CONNECT www.example.com:80 HTTP/1.0

HTTP/1.1 200 Connection established

Expected behavior

proxy.py should return a 407 Proxy Authentication Required result.

Version information

This problem also reproduces with the current develop branch (5e02436).

abhinavsingh commented 1 year ago

@larsks Unsure if this has started happening after any recent commit or has this been always the case. Nevertheless, thanks for reporting this. Really appreciate it. I'll get this out fixed soon. Best.

dongfangtianyu commented 11 months ago

I encountered the same problem and easily reproduced it.

Tracking https://github.com/abhinavsingh/proxy.py/blob/develop/proxy/http/proxy/auth.py#L30 The variables here,

The value of request.headers was found to be None, so the entire validation logic was skipped

if self.flags.auth_code and request.headers:

I'm not sure why the Boolean value of request.headers is determined here.

My guess is to avoid causing errors in the next line of code not in request. headers .

A simple repair solution is to determine whether to perform authentication checks if the headers are not involved.

Example: https://github.com/dongfangtianyu/proxy.py/blob/develop/proxy/http/proxy/auth.py#L30

abhinavsingh commented 11 months ago

Thank you @dongfangtianyu for bringing my attention back to this. Do you want to send a PR for the same? Will be happy to review/merge. Best

dongfangtianyu commented 11 months ago

Thank you @dongfangtianyu for bringing my attention back to this. Do you want to send a PR for the same? Will be happy to review/merge. Best

Sure, I'm happy to do it. I'm currently getting familiar with the contribution guidelines and test cases, and I will try to submit the PR later.

abhinavsingh commented 2 months ago

Thank you folks, closing this now

abhinavsingh commented 2 months ago

I'll cut a 2.4.4 soon, so that 2.4.3 is no longer the default install which contains this vulnerability.