August 8, 2019·5 min read·engineeringpostgresqlsecuritytypes

PostgreSQL 11.5 closes a temporary type privilege escalation

A temporary type could capture an inexact function call inside a privileged function. PostgreSQL 11.5 tightens functional cast resolution and fixes several other security issues.

A function call can also be a type conversion, and that overlap matters when a function executes with elevated privileges. PostgreSQL 11.5 closes a path where an attacker could create a temporary type that captures an inexact call inside a suitable SECURITY DEFINER function. The resulting SQL executes under the function owner's identity.

The August 8 announcement identifies this as CVE-2019-10208. It also includes a server-memory disclosure fix and two EnterpriseDB Windows installer security fixes. The release is relevant across the supported branches, although the individual vulnerabilities have different scopes.

I prefer PostgreSQL's explicit privilege mechanisms to application conventions that merely assume a caller is trusted. Those mechanisms still depend on correct name and type resolution. A privileged function must not accidentally interpret an attacker's temporary object as part of its own intended computation.

Inexact argument matches create an opportunity

The announcement gives a concise distinction using length. A call with an explicitly typed text argument is an exact match in its example. Calls with a varchar argument or an untyped string literal are inexact. This is relevant because the attack requires a privileged function containing a call with an inexact argument-type match.

The attacker also needs permission to execute the suitable SECURITY DEFINER function. The temporary object involved is a domain created in a pg_temp schema. These prerequisites distinguish the vulnerability from a claim that any arbitrary function call gives any user elevated access.

The 11.5 release notes explain the repair through functional cast syntax. PostgreSQL already requires explicit temporary-schema qualification when invoking a temporary function. It now applies the corresponding requirement when functional notation casts to a temporary type.

That correspondence matters because a spelling that looks like a function invocation can resolve as a conversion to a type. Restricting temporary function lookup is insufficient if temporary types can still capture the same syntactic form. The fix closes the alternate route through type conversion.

The release notes compare the privilege-escalation pattern with CVE-2007-2138. That older identifier is historical context for the attack pattern and the fix. It is not a third newly disclosed server issue in this maintenance release.

The immediate consequence for privileged functions is that resolution rules form part of the security model. A function owner's authority is intentionally available to the function's work. An attacker must not be able to change what that work calls by introducing a temporary object with a strategically chosen name.

Hash comparison must use the stored value types

The other server issue, CVE-2019-10209, concerns hashed subplans requiring cross-type comparison. The implementation used the outer query's original comparison operator to compare entries within the hash table. That is incorrect because those stored entries all have the subquery's output type.

This is a different kind of type error from the temporary-domain issue. There, name resolution could select an unintended interpretation. Here, execution selected an operator appropriate to the original cross-type comparison and reused it where both operands had another relationship.

The release notes describe different consequences depending on operators and machine architecture. For core hashable cross-type operators, the mistake appears nearly harmless on 64-bit machines, while 32-bit machines can suffer crashes or possible unauthorized disclosure. Extensions may provide operators that create greater risks.

The announcement emphasizes unusual user-defined hash equality operators and says a superuser would need to create the operators for the described attack to become possible. The notes provide additional implementation context. Neither account supports treating every PostgreSQL 11 hashed subplan as an equally exposed memory-disclosure path.

This distinction is useful for extension users in particular. PostgreSQL's extensibility allows operator definitions that the core implementation cannot assume behave like a fixed built-in set. Reusing an operator in the wrong type context can therefore have consequences beyond those visible in ordinary built-in cases.

Windows installation adds two separate exposures

CVE-2019-10210 concerns a temporary file containing the PostgreSQL superuser password during installation. The EnterpriseDB Windows installer created the file in its installation directory, initialized the databases and deleted the file. A local attacker could read it during the interval when it existed.

Deletion after use did not establish confidentiality during use. The file's permissions and location mattered while the password remained present. This issue concerns installation behavior for versions 9.4 through 11, independently of whether a running database uses a vulnerable privileged function.

CVE-2019-10211 concerns bundled OpenSSL configuration. The advisory says libeay32.dll attempted to read configuration from a hard-coded directory. A local user could create that normally absent directory and supply configuration that directs OpenSSL to load code.

That exposure can affect the database server or a libpq client when initializing SSL. The relevant identity is the operating-system account running the affected process. It therefore crosses the same installation package into both server and client use, rather than being confined to a SQL statement executed by an authenticated database user.

My preference is to keep these distinctions visible when evaluating an update. A temporary-schema resolution fix, a hash-operator type correction and an installer permission repair require different explanations. Grouping them under one version number is convenient for distribution, but it does not make their prerequisites interchangeable.

Some repairs leave existing catalog state unchanged

The maintenance changes also prevent indirect deletion of partition-key columns. Direct column deletion already had a check, but a cascading drop of a custom data type could remove the key indirectly and leave a broken partitioned table. New dependency entries ensure that such a cascade affects the whole table appropriately.

The notes explicitly limit that protection to newly created partitioned tables. Replacing the binaries does not add those dependency entries to existing tables. The announcement identifies recreating the table and moving data, or using pg_upgrade, as remedies where this applies.

The release also repairs a regression in altering multiple column types in one command and an incorrect parallel hash semi-join that could duplicate results from some EXISTS queries. These are correctness fixes alongside the security work. Installing the maintenance release does not generally require a dump and reload, while the partition dependency issue retains its separate requirements for existing objects.