Zion Boggan

In-depth vulnerability research, detection engineering & applied cryptography.

● Open to security-research & detection roles
GitHub · LinkedIn · Email
← Research notebook
Sandbox bypass

Report: aiven_gatekeeper Bypass via Implicitly Castable Argument Types

Metadata

  • Target: Aiven for PostgreSQL (Tier 2)
  • Target Location: Aiven for PostgreSQL
  • Target Category: Other
  • VRT: Server Security Misconfiguration > Database Management System (DBMS) Misconfiguration > Excessively Privileged User / DBA
  • Priority: P2 (Suggested)

Title

aiven_gatekeeper Fails to Prevent pghostile-Style Function Shadowing When Shadow Uses Implicitly Castable Argument Types

Summary

The aiven_gatekeeper shared library (Aiven’s PostgreSQL security agent) is designed to prevent privilege escalation attacks where unprivileged users create shadow functions in the public schema that override pg_catalog system functions. However, aiven_gatekeeper only blocks shadow functions with identical argument signatures. It fails to block shadow functions with different but implicitly castable argument types.

For example, pg_catalog.sha256(bytea) is protected, creating public.sha256(bytea) is blocked. But creating public.sha256(text) is allowed, and this shadow function is called INSTEAD of the pg_catalog version when a user calls sha256('string_literal'), because PostgreSQL’s function resolution prefers text→text (exact match) over text→bytea (implicit cast).

Aiven’s own tool pghostile (https://github.com/Aiven-Open/pghostile) identifies ~907 exploitable function overrides using this technique. The gatekeeper was designed to prevent exactly this class of attack but fails for cross-type shadows.

Steps to Reproduce

Step 1: Create shadow function with different argument type

CREATE OR REPLACE FUNCTION public.sha256(text) RETURNS bytea AS $$
BEGIN
 RAISE WARNING 'SHADOW FIRED: cu=% su=%', current_user, session_user;
 RETURN pg_catalog.sha256($1::bytea);
END;
$$ LANGUAGE plpgsql;

Step 2: Verify the shadow fires

SELECT sha256('test');
-- WARNING: SHADOW FIRED: cu=avnadmin su=avnadmin

The shadow function in public is called instead of pg_catalog.sha256(bytea) because sha256(text) is a better match when the argument is a text literal.

Step 3: Verify gatekeeper would block identical signature

-- This WOULD be blocked by gatekeeper (if attempted via pghostile):
-- CREATE FUNCTION public.sha256(bytea) ...
-- But our text-argument version bypasses the check entirely.

Impact

  1. Defeats pghostile protection: aiven_gatekeeper was specifically built to prevent the attack class that pghostile exploits. The implicit cast bypass renders this protection incomplete.

  2. Superuser code execution via autovacuum: When combined with expression indexes, the shadow function executes in the autovacuum worker context with session_user=postgres (see related report: Autovacuum Code Execution).

  3. Broad attack surface: pghostile identifies ~907 exploitable functions. Many of these have variants with different-but-castable argument types that bypass gatekeeper.

Recommended Fix

Extend aiven_gatekeeper to block function creation in public (and other user-accessible schemas) when the function name matches ANY pg_catalog function, regardless of argument types. Alternatively, block functions whose names match pg_catalog functions when the argument types are implicitly castable to the pg_catalog version’s argument types.


Source · github.com/zionsworking/security-research-notebook · writeups/aiven/pg-gatekeeper-bypass-shadow-functions.md