-
Vulnerability Name: Public Health Check Endpoint Information Disclosure
-
Description:
An unauthenticated health check interface is exposed at the/ht/
endpoint. An external attacker can send a specially crafted GET request (for example, with the query parameterformat=json
) and receive a JSON response that contains detailed status messages from various internal health‐check plugins. These messages are generated by each plugin’spretty_status()
method and may include internal error messages (e.g. “Integrity Error”, “Database error”, “ServiceUnavailable” errors, etc.). The report is constructed directly from the plugins without sanitization, which could divulge details about the underlying internal systems, mis-configured storage backends, database issues, or task queue errors. -
Impact:
- An attacker can collect in-depth information about internal components of the system.
- Sensitive error details or configuration indicators (such as plugin names and specific error texts) may expose weaknesses that can be leveraged in further attacks (for example, targeting the database, cache, or messaging systems).
- The disclosure of internal error messages can assist a threat actor in performing reconnaissance to craft more targeted exploits.
-
Vulnerability Rank: High
-
Currently Implemented Mitigations:
- The project follows a “fail‑fast” health check design where errors are collected and output in the response.
- The endpoints were intentionally left open to support the use case of external monitoring.
- There is no mechanism at the code level that restricts access or sanitizes internal error details from the response.
-
Missing Mitigations:
- Access Control: No authentication or IP‐whitelisting is applied to the health check endpoints.
- Error Sanitization: The responses directly relay error messages from each health check plugin without filtering out sensitive internal information.
- Output Filtering: There is no option to limit the detail level (or to return generic “working”/“failure” indicators) when errors occur.
- Rate Limiting: Although not directly exploited here, no measures exist to limit repeated requests that might further aid an attacker’s reconnaissance.
-
Preconditions:
- The
/ht/
(or/ht/?format=json
) endpoint is publicly accessible (as recommended by the project README for monitoring purposes). - At least one underlying health check plugin has encountered an error or is returning status details (for example, due to a misconfigured database or messaging service).
- The system is deployed in a production environment where the default error strings are not replaced by generic messages.
- The
-
Source Code Analysis:
- In
health_check/views.py
within theMainView.get
method, the code retrieves the HTTP Accept header (or a format override via a query parameter) and then callsself.filter_plugins(subset=subset)
to obtain all registered health check plugins. - When a JSON response is demanded, the method calls
render_to_response_json
, which builds a JSON object mapping each plugin’s identifier to the result of itspretty_status()
method. - The
pretty_status()
method inhealth_check/backends.py
formats error messages by simply joining error strings with newline characters without sanitization. - Because no processing is done to remove or generalize internal error details, an external GET request (with
Accept: application/json
orformat=json
) will return all plugin status messages verbatim.
- In
-
Security Test Case:
- Deploy the application (with the health check endpoints enabled as configured in the project README).
- From an external client, send a GET request to the public endpoint—for example:
curl -X GET "http://[target-domain]/ht/?format=json"
- Observe that the JSON response contains key/value pairs where keys represent the identifier of each registered health check plugin (e.g.
"DatabaseBackend"
,"Cache backend: default"
, etc.) and values reflect their status (including detailed error messages if any). - Verify that at least one of these error messages includes internal details (such as specific exception types or error phrases) that could reveal sensitive information about the backend systems.
- Conclude that an attacker can directly obtain internal system details without any access control or output sanitization in place.
-
====================================================================================================
-
Vulnerability name: HTTP Accept Header Parsing Vulnerability (ReDoS)
-
Description:
- Step 1: An attacker sends an HTTP GET request to the health check endpoint (e.g.,
/ht/
). - Step 2: The attacker crafts a malicious
Accept
header with a long string containing repeated and complex patterns designed to exploit regex backtracking. Example malicious header:Accept: text/html,text/html,text/html,...
orAccept: text/html;q=0.1,text/html;q=0.1,text/html;q=0.1,...
or even more complex patterns using media type parameters. - Step 3: The Django application, using
django-health-check
, receives the request and theMainView.get
method is invoked. - Step 4: Inside
MainView.get
, theMediaType.parse_header
function is called to parse theAccept
header using a regular expression. - Step 5: The crafted malicious
Accept
header causes the regular expression engine to perform excessive backtracking due to the regex pattern's structure and the input's complexity. - Step 6: This backtracking consumes a significant amount of CPU resources on the server.
- Step 7: The server's performance degrades, potentially leading to slow response times for all users or even service unavailability.
- Step 1: An attacker sends an HTTP GET request to the health check endpoint (e.g.,
-
Impact: High. Successful exploitation can lead to excessive CPU consumption, resulting in degraded performance and potential service disruption for legitimate users.
-
Vulnerability rank: High
-
Currently implemented mitigations: None. The project does not currently implement any specific mitigations against ReDoS attacks in the
Accept
header parsing logic. -
Missing mitigations:
- Implement a more efficient and secure method for parsing the
Accept
header, potentially avoiding complex regular expressions or using ReDoS-resistant regex patterns. - Introduce a limit on the length or complexity of the
Accept
header that the application will process to prevent excessively long or complex inputs from triggering ReDoS. - Implement request timeouts to limit the processing time for individual requests, mitigating the impact of ReDoS by preventing a single request from monopolizing server resources for too long.
- Consider using a dedicated, well-vetted library for HTTP header parsing which is designed to be robust against such attacks.
- Implement a more efficient and secure method for parsing the
-
Preconditions:
- The
django-health-check
application is installed and enabled in a Django project. - The health check endpoint (e.g.,
/ht/
) is publicly accessible without any rate limiting or WAF rules in place to block malicious requests. - The server has limited CPU resources or is under load, making it susceptible to resource exhaustion from CPU-intensive operations.
- The
-
Source code analysis:
- The vulnerability is located in
health_check/views.py
within theMediaType
class, specifically in thepattern
attribute and theparse_header
method. - The
pattern
is a compiled regular expression designed to parse the components of an HTTPAccept
header. - The regex pattern
r"""..."""
uses quantifiers like*
which, combined with nested groups and alternations, can lead to catastrophic backtracking when processing maliciously crafted input strings. - The
parse_header
method splits theAccept
header string by commas and then usesMediaType.from_string
to parse each media type component using the vulnerable regex. - A crafted
Accept
header with repeated or nested patterns can cause the regex engine to explore a large number of backtracking paths, leading to increased CPU usage and processing time.
class MediaType: pattern = re.compile( r""" ^ (?P<mime_type> (\w+|\*) # Media type, or wildcard / ([\w\d\-+.]+|\*) # subtype, or wildcard ) ( \s*;\s* # parameter separator with optional whitespace q= # q is expected to be the first parameter, by RFC2616 (?P<weight> 1([.]0{1,3})? # 1 with up to three digits of precision | 0([.]\d{1,3})? # 0.000 to 0.999 with optional precision ) )? ( \s*;\s* # parameter separator with optional whitespace [-!#$%&'*+.^_`|~0-9a-zA-Z]+ # any token from legal characters = [-!#$%&'*+.^_`|~0-9a-zA-Z]+ # any value from legal characters )* $ """, re.VERBOSE, ) @classmethod def parse_header(cls, value="*/*"): """Parse HTTP accept header and return instances sorted by weight.""" yield from sorted( ( cls.from_string(token.strip()) for token in value.split(",") if token.strip() ), reverse=True, )
- The vulnerability is located in
-
Security test case:
- Step 1: Deploy the
django-health-check
application to a test server and ensure the health check endpoint is accessible. - Step 2: Monitor the CPU usage of the server using tools like
top
,htop
, or cloud provider monitoring dashboards to establish a baseline CPU usage when the health check endpoint is accessed normally. - Step 3: Use a tool like
curl
,Postman
, or a custom script to send an HTTP GET request to the health check endpoint (/ht/
) with a crafted, maliciousAccept
header. A sample malicious header could be:Accept: text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html,text/html
- Step 4: While sending the malicious request, monitor the server's CPU usage.
- Step 5: Observe if there is a significant increase in CPU usage compared to the baseline established in Step 2. If the CPU usage spikes and remains high during and after the request, and the response time is significantly delayed or the server becomes unresponsive, it confirms the ReDoS vulnerability.
- Step 1: Deploy the
-