A vulnerability has been discovered in the popular Python HTTP client library urllib3, which could potentially expose sensitive data in HTTP request bodies when handling certain redirect responses. This issue is identified as CVE-2023-45803.

Description

urllib3 is a widely used, user-friendly HTTP client library for Python. The library previously failed to remove the HTTP request body when it encountered an HTTP redirect response with status codes 301, 302, or 303, even after the request's method was changed from one that could accept a request body (such as POST) to GET. This behavior is required by HTTP RFCs. However, it is not explicitly stated in the section related to redirects, but can be inferred by examining information from various sections and observing the behavior in other major HTTP client implementations like curl and web browsers.

The exploitability of this vulnerability is considered to be low, given that it requires a previously trusted service to become compromised for it to have any impact on confidentiality. Additionally, many users do not put sensitive data in HTTP request bodies, rendering the vulnerability inapplicable in those cases.

To be affected by this vulnerability, both of the following conditions must be true

1. The user is utilizing urllib3 while submitting sensitive data in the HTTP request body (e.g., form data or JSON).
2. The origin service becomes compromised and begins redirecting using status codes 301, 302, or 303 to a malicious peer, or the redirected-to service is compromised.

The following code snippet demonstrates an example of a vulnerable usage of urllib3

import urllib3

http = urllib3.PoolManager()

response = http.request(
    "POST",
    "https://example.com/api";,
    fields={"field1": "sensitive_data"},
)

Solution

This issue has been addressed in urllib3 versions 1.26.18 and 2..7. Users are advised to update their urllib3 library to one of these versions to resolve the issue.

If users are unable to update their library, they should disable redirects for services that are not expected to respond with redirects using the redirects=False parameter and handle 301, 302, and 303 redirects manually by stripping the HTTP request body in the following manner:

import urllib3

http = urllib3.PoolManager()

response = http.request(
    "POST",
    "https://example.com/api";,
    fields={"field1": "sensitive_data"},
    redirects=False,
)

if response.status in (301, 302, 303):
    # Handle the redirect manually by stripping the request body
    response = http.request("GET", response.get_redirect_location(), redirects=False)

References

For more information on this issue, please refer to the original urllib3 GitHub advisory and urllib3 releases page for the latest updates.

Timeline

Published on: 10/17/2023 20:15:10 UTC
Last modified on: 11/03/2023 22:15:11 UTC