Skip to content

Latest commit

 

History

History
162 lines (128 loc) · 13.1 KB

File metadata and controls

162 lines (128 loc) · 13.1 KB

Combined Vulnerability Report

This report combines identified vulnerabilities from multiple sources into a single list, removing duplicates and providing detailed descriptions, impacts, mitigations, and test cases for each vulnerability.

Vulnerability 1: Missing Default Origin Validation on WebSocket Connections

Description: The Channels framework offers an OriginValidator for WebSocket connections to prevent Cross-Site WebSocket Hijacking (CSWSH) attacks. However, this validator is not enabled by default. If developers fail to explicitly implement origin validation middleware for their WebSocket consumers, connections from any origin, including malicious ones, will be accepted. An attacker can craft a WebSocket connection request from a malicious domain, setting an arbitrary Origin header. Without default validation, the application will accept this connection, potentially exposing sensitive data or allowing unauthorized actions through the WebSocket.

Impact:

  • Establishment of WebSocket connections from hostile domains.
  • Facilitation of Cross-Site WebSocket Hijacking (CSWSH) attacks.
  • Potential for session impersonation and unauthorized actions.
  • Exposure of sensitive data transmitted via WebSocket if session cookies are used for authentication.

Vulnerability Rank: High

Currently Implemented Mitigations:

  • The Channels project provides OriginValidator and AllowedHostsOriginValidator in channels/security/websocket.py.
  • Tests demonstrate that these validators function correctly when applied, rejecting connections from disallowed origins.

Missing Mitigations:

  • Origin validation is not enforced by default for WebSocket consumers. Developers must manually apply the OriginValidator middleware.
  • There is a lack of clear documentation or secure defaults that would automatically enable origin validation, increasing the risk of developers overlooking this crucial security measure.

Preconditions:

  • The Channels application exposes one or more WebSocket endpoints.
  • The deployed application does not utilize origin validation middleware like OriginValidator or AllowedHostsOriginValidator.
  • Allowed origins are either not configured or are misconfigured to permit untrusted origins.

Source Code Analysis:

  • Located in channels/security/websocket.py, the OriginValidator.__call__ method is designed to validate the Origin header of incoming WebSocket connections.
  • The method parses the Origin header and uses helper methods valid_origin and validate_origin to check against a list of allowed origins.
  • However, Channels does not enforce the use of this validator by default.
  • If a developer does not explicitly wrap their WebSocket consumer with OriginValidator, the connection request bypasses origin checks and is passed directly to the application.
  • The absence of default origin validation means that applications are vulnerable unless developers proactively implement this security measure.

Security Test Case:

  1. Deploy a Channels application with a WebSocket consumer, ensuring that OriginValidator middleware is not applied.
  2. Use a WebSocket testing tool (e.g., WebsocketCommunicator or websocat) to initiate a connection to the WebSocket endpoint.
  3. In the connection request, include an Origin header with a malicious domain, such as http://malicious.com.
  4. Verify that the WebSocket connection is successfully established, demonstrating the missing origin validation.
  5. Next, modify the application to wrap the WebSocket consumer with AllowedHostsOriginValidator, configured to allow only trusted domains (e.g., http://trusted.com).
  6. Repeat the connection attempt with the same malicious Origin header (http://malicious.com).
  7. Confirm that the connection is now rejected, demonstrating the effectiveness of the OriginValidator when correctly implemented.

Vulnerability 2: Insecure Default Cookie Settings in Session Management

Description: The session middleware in Channels, specifically within channels/sessions.py, uses CookieMiddleware.set_cookie to set session cookies in HTTP responses. By default, critical cookie parameters like secure and samesite are not set to secure values. For instance, secure defaults to False, and samesite defaults to "lax". In production environments using HTTPS, if developers do not override these defaults by setting Django settings like SESSION_COOKIE_SECURE = True, session cookies might be transmitted over unencrypted HTTP or lack strong "SameSite" restrictions. This can enable attackers with network access to intercept session cookies and hijack user sessions.

Impact:

  • Session hijacking due to interception of session cookies transmitted without the Secure flag over non-TLS channels.
  • Increased susceptibility to Cross-Site Request Forgery (CSRF) and related attacks if cookie attributes are not restrictively configured.
  • Unauthorized access to user accounts and sensitive application functionalities through the reuse of hijacked session cookies.

Vulnerability Rank: High

Currently Implemented Mitigations:

  • The CookieMiddleware.set_cookie method in channels/sessions.py allows setting cookie parameters such as secure, httponly, and samesite.
  • Developers can configure these parameters using Django settings like SESSION_COOKIE_SECURE, SESSION_COOKIE_SAMESITE, etc.

Missing Mitigations:

  • Channels does not enforce secure cookie attributes (like secure=True) by default in production environments.
  • Relying solely on developer configuration creates a risk if defaults are not explicitly overridden, leading to insecure cookie settings in deployed applications.
  • There are no built-in warnings or automatic fallbacks to alert developers about insecure cookie settings in publicly accessible instances.

Preconditions:

  • The Channels application is deployed with default Django session settings, which often have SESSION_COOKIE_SECURE = False in development.
  • The application is running in an environment exposed to public traffic, potentially including non-TLS channels or with weak cookie security configurations.
  • An attacker is positioned to observe or intercept HTTP traffic, such as through a man-in-the-middle attack on an open Wi-Fi network.

Source Code Analysis:

  • In channels/sessions.py, the CookieMiddleware.set_cookie method constructs cookies using Python's SimpleCookie routines.
  • Default settings within this method include secure=False (unless overridden) and samesite="lax".
  • The code does not automatically enforce stricter security defaults like Secure and HttpOnly in production, leaving it to developers to configure these through Django settings.
  • This "opt-in" approach to secure cookie settings can result in insecure cookie transmission if developers fail to modify the default settings before deploying a Channels-based application to production.

Security Test Case:

  1. Deploy a Channels application using session middleware with default settings, without modifying Django’s default SESSION_COOKIE_SECURE and related settings.
  2. Initiate an HTTP request (using curl or a browser) that results in a session cookie being set in the response.
  3. Capture the response headers and examine the Set-Cookie header. Verify that the Secure flag is missing and SameSite is set to "lax".
  4. In a production-like deployment or by simulating an HTTP environment, use a network proxy (e.g., Wireshark or mitmproxy) to confirm that the session cookie is transmitted in cleartext over HTTP.
  5. Simulate an attacker intercepting the session cookie and then reusing it in a subsequent request to demonstrate successful session hijacking.
  6. As a corrective test, update Django settings to enforce stricter parameters (e.g., set SESSION_COOKIE_SECURE = True). Verify that the Set-Cookie header now includes secure attributes and that intercepted cookies are no longer transmitted over insecure channels when using HTTPS.

Vulnerability 3: Origin Validation Bypass in Websocket Connections

Description: The OriginValidator middleware in channels.security.websocket aims to prevent Cross-Site WebSocket Hijacking (CSWSH) by validating the Origin header of WebSocket connections against allowed origins. However, the validation logic in OriginValidator.match_allowed_origin can be bypassed. An attacker can craft an Origin header that includes a valid allowed origin as a subdomain of a malicious domain (e.g., allowed-domain.com.attacker-domain.com), tricking the validator. The is_same_domain function, used for origin matching, incorrectly validates such origins, leading to a bypass of the intended origin check and allowing malicious WebSocket connections.

Impact:

  • Critical
  • Successful exploitation allows an attacker to circumvent origin validation and establish WebSocket connections from malicious websites, leading to Cross-Site WebSocket Hijacking (CSWSH).
  • This can enable attackers to perform unauthorized actions on behalf of authenticated users if the application uses session-based authentication and WebSockets for sensitive operations.

Vulnerability Rank: Critical

Currently Implemented Mitigations:

  • The project utilizes OriginValidator middleware to check the Origin header, located in /code/channels/security/websocket.py.

Missing Mitigations:

  • The is_same_domain function used in OriginValidator.match_allowed_origin is too permissive and vulnerable to subdomain bypasses.
  • The missing mitigation is to implement stricter origin validation logic that prevents subdomain bypasses. This could involve directly comparing hostnames after parsing and ensuring no subdomain matching occurs unless explicitly intended through wildcard configurations.

Preconditions:

  • The Channels application uses OriginValidator middleware with a list of allowed origins.
  • WebSocket connections are used for sensitive operations within the application.
  • The allowed origins list contains domain names without wildcards or with wildcard patterns that are not strictly defined to prevent subdomain matching vulnerabilities.

Source Code Analysis:

  • Code location: /code/channels/security/websocket.py
def match_allowed_origin(self, parsed_origin, pattern):
    """
    ...
    """
    if parsed_origin is None:
        return False

    # Get ResultParse object
    parsed_pattern = urlparse(pattern.lower())
    if parsed_origin.hostname is None:
        return False
    if not parsed_pattern.scheme:
        pattern_hostname = urlparse("//" + pattern).hostname or pattern
        return is_same_domain(parsed_origin.hostname, pattern_hostname) # Vulnerable line
    # ...
  • The vulnerability lies in the line return is_same_domain(parsed_origin.hostname, pattern_hostname).
  • is_same_domain from django.http.request performs a check that incorrectly considers subdomains of the allowed host as valid.
  • For example, with allowed_origins including allowed-domain.com, is_same_domain incorrectly returns True for both allowed-domain.com and subdomain.allowed-domain.com.
  • This flawed logic is exploited when an attacker uses allowed-domain.com.attacker-domain.com as the origin. is_same_domain compares allowed-domain.com.attacker-domain.com with allowed-domain.com and erroneously returns True because allowed-domain.com is considered a "domain" of allowed-domain.com.attacker-domain.com based on is_same_domain's suffix matching logic.
# django/http/request.py
def is_same_domain(server_name, hostname):
    """
    Return ``True`` if the two hostnames are equal.

    If either hostname is a wildcard, return ``True`` if the non-wildcard
    hostname matches the wildcard.
    """
    server_name = server_name.lower()
    hostname = hostname.lower()
    if hostname.startswith('.'):
        return server_name.endswith(hostname)
    return server_name == hostname
  • Django's is_same_domain implementation checks for suffix matches if hostname starts with .. While wildcard patterns are not directly used in the provided vulnerability description, the is_same_domain function still treats allowed-domain.com as a potential "domain" and incorrectly allows subdomains of attacker-controlled domains to pass the origin check if they embed the allowed domain as a subdomain.

Security Test Case:

  1. Set up a Channels application that employs OriginValidator middleware with allowed_origins = ["allowed-domain.com"].
  2. Prepare a malicious website hosted on attacker-domain.com.
  3. On the malicious website, create a JavaScript WebSocket client to connect to the Channels application's WebSocket endpoint.
  4. In the WebSocket client's connection request, set the Origin header to http://allowed-domain.com.attacker-domain.com.
  5. Observe the WebSocket connection attempt from the malicious website.
  6. Expected Result: The WebSocket connection is accepted by the Channels application, indicating a successful bypass of origin validation.
  7. Correct Behavior: The WebSocket connection should be rejected because the origin http://allowed-domain.com.attacker-domain.com is not in the allowed origins list and originates from a different domain (attacker-domain.com).