Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
postgres-basebackup-symlink — PostgreSQL 18.6 - High - Remote - File write - pg_basebackup follows absolute tar symlink leftover of CVE-2026-6475 | Kitploit
Tools/GitHubGitHub/abraxas/postgres-basebackup-symlink
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingPapers & ResearchDatabase SecurityLabs & Practice
GitHub
abraxas/postgres-basebackup-symlink

postgres-basebackup-symlink

PostgreSQL 18.6 - High - Remote - File write - pg_basebackup follows absolute tar symlink leftover of CVE-2026-6475

View Repository
63 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Abraxas Labs - postgres-basebackup-symlink

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  postgres-basebackup-symlink

postgres-basebackup-symlink

Class: File write Reach: Remote

PostgreSQL 18.6 (724edf9) - PostgreSQL Global Development Group

CVE-2026-6475 added path_is_safe_for_extraction for tar member names. Absolute symlink targets still skip that check so tablespaces work. astreamer_file.c then symlink()s the target and later fopen(..., "wb") follows it. Default pg_basebackup format is plain (-F p). pg_rewind create_target_symlink checks path and never link.

A hostile source that speaks BASE_BACKUP can plant an absolute symlink and overwrite any file the backup UID can write. Same victim model as 6475. This is not a re-file of the member-name checks.

IDno CVE yet
ClassFile write (absolute tar symlink leftover of CVE-2026-6475)
ReachRemote (UI:R client vs hostile PostgreSQL)
CWECWE-59, CWE-22
CVSSHigh: 8.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
ProductPostgreSQL
Affected18.6 tag REL_18_6 (724edf9bde9d356724ad384a2e196edc3c9f80f7), in-tree pg_basebackup / pg_rewind
Authvictim runs default pg_basebackup -D <dir> against an attacker source
LicenseGNU Affero GPL v3.0
Lab127.0.0.1 only

What an attacker can do

Someone who can get an operator to run pg_basebackup -D against their PostgreSQL (the same UI:R model as CVE-2026-6475) can write outside -D.

PrivilegeMethod / sinkLab-proven or inferred
Integrity: write a file outside -DHostile BASE_BACKUP tar: typeflag '2' member with a safe relative name (pg_tblspc/16384) and an absolute link target, then a regular member under that name. extract_link then create_file_for_extract fopen(..., "wb") with no O_NOFOLLOWLab-proven. Wrote POSTGRES-BASEBACKUP-SYMLINK-WITNESS at /work/oracle/. Dest holds the symlink. Control tar (no symlink) left the oracle empty and wrote PG_VERSION only inside -D
Integrity: overwrite shell rc, authorized_keys, a systemd user unit, or crontabSame sink, any path the client UID can writeInferred. This lab does not touch those files
Availability: smash client config or keysSame writeInferred. Not demonstrated
Recon of the client diskextract is write, not readClosed
Walk .. or absolute member namespath_is_safe_for_extractionClosed. That is CVE-2026-6475
Server-side unpriv SQL / unauth protocol18.6 default serverClosed. This leftover is the client
Tar-only backuppg_basebackup -F t stores the tar without extractingClosed
RCE inside postgresnot this sinkClosed

pg_rewind has the same create_target_symlink / open() leftover. This lab drives pg_basebackup only.

How I found it

I pinned postgres/postgres REL_18_6 after the 18.6 wave (28 CVEs, plus the 18.4/18.2 set already on this tree). Twenty-two hunts. Default server, unpriv SQL, unauth protocol: none at this bar. CVE-2026-6475 was the sibling to re-read.

Member names are checked. Absolute symlink targets are not:

if (!is_absolute_path(linktarget) &&
    !path_is_safe_for_extraction(member->linktarget))
{
    pg_fatal("link target has unsafe path name: \"%s\"",
             member->linktarget);
}
extract_link(mystreamer->filename, linktarget);

create_file_for_extract is still fopen(filename, "wb"). Comment at astreamer_file.c:351-356 says mapping is applied without checking the link is inside pg_tblspc.

Wrong turns already recorded: treating 6475 as closed and walking away; pointing -D at a live data directory; overwriting shell rc for theatre. An honest 18.6 server only emits pg_tblspc/<oid> symlinks and puts tablespace contents in a separate archive. A malicious source that speaks BASE_BACKUP can put the follow-up regular member in the same tar. That is the leftover.

Lab

python3 postgres-basebackup-symlink-Abraxas-Labs.py

or

cd lab
./run.sh

postgres:18.6 as the source image, running a BASE_BACKUP speaker. Client is in-tree pg_basebackup from the same tag (pg_basebackup (PostgreSQL) 18.6). Loopback 127.0.0.1:19370. Compose project postgres-basebackup-symlink. Do not point -D at a live data directory.

SUCCESS postgres-basebackup-symlink control-inside=yes oracle-outside=yes dest-is-symlink=yes image=postgres:18.6 how=pg_basebackup POSTGRES-BASEBACKUP-SYMLINK-WITNESS

The fix

Treat absolute symlink targets as unsafe unless they are rewritten by --tablespace-mapping. Open extract files with O_NOFOLLOW / lstat so a planted link cannot be followed. Apply path_is_safe_for_extraction to rewind link as well as path. Reject a regular member whose path walks through a symlink that left -D.

References

  • github.com/postgres/postgres tag REL_18_6 (724edf9bde9d356724ad384a2e196edc3c9f80f7)
  • src/fe_utils/astreamer_file.c · src/fe_utils/astreamer_tar.c
  • src/bin/pg_rewind/file_ops.c
  • Nearby patched (member names, not this target): CVE-2026-6475
  • CWE-59 · CWE-22

License

GNU Affero GPL v3.0. See LICENSE. Loopback lab only. No warranty.

Download Tool