Perl’s %ENV Bypass in Trusted Extensions

▶ Watch (3:20)

PostgreSQL extensions support multiple languages, split into trusted and untrusted. Untrusted languages like C can spawn processes and access the filesystem, but only superusers can invoke them. Trusted languages like PL/Perl run without superuser rights. Perl includes a built-in magic hashmap called %ENV for reading and writing environment variables. PL/Perl does not override it. A non-superuser can call a PL/Perl function that modifies the session process’s environment variables, an operation PostgreSQL reserves for superusers.

PL/Rust’s Incomplete Deny List Opens Code Execution

▶ Watch (4:49)

PL/Rust compiles Rust functions by calling cargo directly from the PostgreSQL process. When a PL/Rust function is created, cargo sets up the build environment and calls rustc. PL/Rust removes dangerous environment variables before invoking cargo, but uses a deny list. The list strips RUSTC_WRAPPER but not CARGO_BUILD_RUSTC_WRAPPER, which has the same effect: it swaps the binary cargo calls instead of rustc. Setting that variable via the PL/Perl primitive redirects cargo to run an attacker-controlled binary.

Shell Injection via rust-gdb

▶ Watch (7:03)

With CARGO_BUILD_RUSTC_WRAPPER set, the attacker cannot control the arguments passed to the swapped binary. The rust-gdb script, installed with Rust, reads a RUST_GDB environment variable and passes its value to gdb. Setting CARGO_BUILD_RUSTC_WRAPPER to point at rust-gdb and RUST_GDB to bash commands achieves shell injection. A PL/Perl function sets both variables. Creating any PL/Rust function triggers compilation, which calls cargo, which calls rust-gdb, which runs the injected commands. The demo shows successful code execution on PostgreSQL with no superuser access required.

Cloud RCE on AWS RDS and the Response

▶ Watch (12:30)

AWS RDS for PostgreSQL ships with both PL/Perl and PL/Rust extensions available, making it a valid target. The researchers ran the exploit against their own RDS instance to check for network access or credential exfiltration from the managed layer. The environment was locked down: no network reach, no cross-tenant paths. AWS incident response detected the activity fast. Emails reached the CEO, AWS located Coby via LinkedIn (the database was named “kobe”), and shut down the instance shortly after.

Notable Quotes

Something could go wrong. Tal Peleg · ▶ 1:35

incident response team is really good. Tal Peleg · ▶ 13:10

do give your database a good name. Tal Peleg · ▶ 17:03

Key Takeaways

  • PL/Perl’s %ENV hashmap lets non-superusers modify environment variables, breaking PostgreSQL’s trusted language boundary.
  • PL/Rust’s deny list missed CARGO_BUILD_RUSTC_WRAPPER, letting cargo run an attacker-controlled binary at compile time.
  • Disable extensions you don’t use; PostgreSQL patched this in all supported versions from 12 onward.

About the Speaker(s)

Tal Peleg, also known as TLP, is a senior security researcher and cloud security team lead at Varonis. He is a full-stack hacker with experience in malware analysis, Windows domains, SaaS applications, and cloud infrastructure. His research focuses on cloud applications and APIs.

Coby Abrams is a cloud security researcher at Varonis, specializing in Azure and IaaS research with in-depth analysis of various services. He brings over five years of experience in security research.