CVE-2021-23222 Overview
CVE-2021-23222 is a man-in-the-middle vulnerability affecting PostgreSQL that allows attackers to inject false responses to the client's first few queries, despite the use of SSL certificate verification and encryption. This vulnerability exploits a timing window during the SSL/GSS encryption handshake process, where a network-positioned attacker can perform a buffer-stuffing attack to inject malicious data before the encrypted channel is fully established.
Critical Impact
Attackers positioned in a man-in-the-middle position can bypass SSL protections and inject unauthorized responses to PostgreSQL clients, potentially compromising data confidentiality even when encryption is enabled.
Affected Products
- PostgreSQL versions prior to security patches
- PostgreSQL 14.0
- Multiple PostgreSQL version branches with libpq client library
Discovery Timeline
- 2022-03-02 - CVE CVE-2021-23222 published to NVD
- 2024-11-21 - Last updated in NVD database
Technical Details for CVE-2021-23222
Vulnerability Analysis
This vulnerability resides in the PostgreSQL client library (libpq) and involves improper handling of data received during the SSL/GSS encryption handshake initialization. The core issue stems from how the frontend handles the transition from unencrypted to encrypted communication.
When SSL encryption is initiated, the server sends a single S byte to indicate SSL readiness, then waits for the frontend to begin the SSL handshake. However, a man-in-the-middle attacker can exploit this transition window by injecting additional bytes into the connection before the SSL handshake completes. These injected bytes are then processed by the client as if they were legitimate server responses.
The vulnerability is classified under CWE-522 (Insufficiently Protected Credentials), as the attack allows credential-related data and query responses to be manipulated before encryption protections are fully in place.
Root Cause
The root cause of CVE-2021-23222 lies in the libpq client library's failure to validate that no extraneous data exists in the connection buffer after the SSL response byte is received but before the SSL handshake completes. The library would process data that arrived during this unencrypted window as if it were legitimate encrypted responses from the server.
The vulnerable code path did not check whether conn->inCursor != conn->inEnd after the SSL handshake completed, meaning any pre-buffered data from an attacker would be trusted and processed.
Attack Vector
This network-based attack requires the attacker to be positioned between the PostgreSQL client and server (man-in-the-middle position). The attack sequence involves:
- Intercepting the initial SSL negotiation between client and server
- Allowing the legitimate S byte response to pass through
- Injecting malicious payload data into the connection stream before SSL is fully established
- The client processes the injected data as legitimate server responses
The attack does not require authentication and does not require user interaction, though it does require the high complexity of achieving a man-in-the-middle position.
// Documentation patch showing the buffer-stuffing attack vector
and proceed without requesting <acronym>SSL</acronym>.
</para>
+ <para>
+ When <acronym>SSL</acronym> encryption can be performed, the server
+ is expected to send only the single <literal>S</literal> byte and then
+ wait for the frontend to initiate an <acronym>SSL</acronym> handshake.
+ If additional bytes are available to read at this point, it likely
+ means that a man-in-the-middle is attempting to perform a
+ buffer-stuffing attack
+ (<ulink url="https://www.postgresql.org/support/security/CVE-2021-23222/">CVE-2021-23222</ulink>).
+ Frontends should be coded either to read exactly one byte from the
+ socket before turning the socket over to their SSL library, or to
+ treat it as a protocol violation if they find they have read additional
+ bytes.
+ </para>
+
<para>
An initial SSLRequest can also be used in a connection that is being
opened to send a CancelRequest message.
Source: GitHub PostgreSQL Commit
Detection Methods for CVE-2021-23222
Indicators of Compromise
- Connection reset or error messages indicating "received unencrypted data after SSL response" in PostgreSQL client logs
- Unexpected query responses or data returned from initial database queries
- Network traffic analysis showing additional payload data between SSL negotiation byte and handshake packets
- Anomalous connection behavior during SSL/TLS establishment with PostgreSQL servers
Detection Strategies
- Deploy network intrusion detection systems (NIDS) to monitor for suspicious traffic patterns during PostgreSQL SSL handshakes
- Implement SSL/TLS traffic inspection at network boundaries to detect injection attempts
- Enable verbose client-side logging in libpq to capture connection establishment anomalies
- Monitor for PostgreSQL client error messages related to SSL handshake failures or unexpected data
Monitoring Recommendations
- Configure logging on database clients to capture SSL negotiation events and errors
- Implement network traffic baselining for PostgreSQL connections to identify anomalous handshake patterns
- Deploy endpoint detection to monitor PostgreSQL client processes for unexpected behavior
- Review firewall and network device logs for potential man-in-the-middle positioning indicators
How to Mitigate CVE-2021-23222
Immediate Actions Required
- Update PostgreSQL client libraries (libpq) to patched versions immediately
- Audit all systems using PostgreSQL client connections for vulnerable library versions
- Implement network segmentation to reduce man-in-the-middle attack surfaces
- Consider using VPN or other encrypted tunnels for PostgreSQL connections until patching is complete
Patch Information
PostgreSQL has released security patches that address this vulnerability by adding validation logic to detect and reject extraneous data received after the SSL response. The fix adds a check in fe-connect.c to verify that no buffered data exists after the SSL handshake completes:
// Security fix validating no unencrypted data in buffer after SSL handshake
pollres = pqsecure_open_client(conn);
if (pollres == PGRES_POLLING_OK)
{
+ /*
+ * At this point we should have no data already buffered.
+ * If we do, it was received before we performed the SSL
+ * handshake, so it wasn't encrypted and indeed may have
+ * been injected by a man-in-the-middle.
+ */
+ if (conn->inCursor != conn->inEnd)
+ {
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("received unencrypted data after SSL response\n"));
+ goto error_return;
+ }
+
/* SSL handshake done, ready to send startup packet */
conn->status = CONNECTION_MADE;
return PGRES_POLLING_WRITING;
Source: GitHub PostgreSQL Commit
For detailed patch information, refer to the PostgreSQL Security Advisory and Gentoo Security Advisory.
Workarounds
- Implement strict network access controls to minimize man-in-the-middle attack opportunities
- Use network isolation for PostgreSQL server connections where possible
- Deploy network monitoring to detect potential MITM attack attempts
- Consider client-side certificate mutual authentication as an additional security layer
# Configuration example - Verify PostgreSQL client library version
psql --version
# Check for patched libpq version in system
ldd $(which psql) | grep libpq
# Update PostgreSQL client packages on Debian/Ubuntu
sudo apt-get update && sudo apt-get upgrade postgresql-client libpq5
# Update on RHEL/CentOS
sudo yum update postgresql postgresql-libs
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


