Skip to content

Latest commit

 

History

History
62 lines (47 loc) · 3.08 KB

File metadata and controls

62 lines (47 loc) · 3.08 KB

CVE-2026-52768 — GLPI-Agent Deploy task Zip Slip in Tools::Archive

  • Advisory: GHSA-g2f7-8mp5-qw65 · CVE-2026-52768
  • Severity: Moderate · CVSS 4.0 AV:A/AC:L/AT:P/PR:H/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
  • CWE: CWE-22 / CWE-23 (path traversal)
  • Affected: glpi-agent < 1.18 — fixed in 1.18. Reported by Pig-Tail via coordinated disclosure.

Root cause

GLPI::Agent::Tools::Archive::_unzip_az() is the pure-Perl ZIP extractor used as a fallback when the unzip binary is absent (and $PREFER_BIN = 0 means it is tried first when Archive::Zip is installed). It builds the destination path by naive concatenation:

my $to = File::Spec->catfile( $extract_dir, $member->{fileName} );  # no normalisation
$zip->extractMember($member, $to);                                  # writes wherever told

File::Spec->catfile() does not collapse or reject .. components, and Archive::Zip::extractMember() writes to the exact path given. A member named ../../etc/cron.d/evil therefore escapes $extract_dir. This is the only extractor in the tool that is vulnerable — the unzip, tar, and 7z binaries all strip or reject ../ components by default.

Reachability

Triggered from the Deploy task (Task/Deploy/Datastore/WorkDir.pm) when a deploy job delivers a ZIP with uncompress, on a host where 7z is not available and Archive::Zip is installed. A malicious archive (delivered through a compromised/MITM GLPI server, or a crafted archive an admin includes in a Deploy package) then writes attacker-controlled content to any path the agent can reach — typically root — enabling persistence (/etc/cron.d, systemd units), credential/authorized_keys overwrite, etc.

PoC

poc/poc_zip_slip.pl reproduces the primitive in isolation, replaying _unzip_az() verbatim with the same Archive::Zip library the agent uses. Everything happens inside one throwaway temp sandbox (no shared /tmp paths); the malicious member ../pwned_<marker> must escape sandbox/extract into sandbox/. Benign marker file, sandbox auto-removed.

cd poc
perl poc_zip_slip.pl    # exit 42 = traversal reproduced

Observed:

[*] extract_dir  : /tmp/XXXX/extract
[*] evil member  : ../pwned_GLPI_ZIPSLIP_CVE_2026_52768
    extract ../pwned_GLPI_ZIPSLIP_CVE_2026_52768 -> /tmp/XXXX/extract/../pwned_GLPI_ZIPSLIP_CVE_2026_52768
[!!] TRAVERSAL CONFIRMED: file written OUTSIDE extract_dir at
     /tmp/XXXX/pwned_GLPI_ZIPSLIP_CVE_2026_52768
 [+] Zip Slip reproduced (arbitrary file write via ../ member)

Requires Archive::Zip (apt install libarchive-zip-perl / cpan Archive::Zip); without it the vulnerable code path doesn't exist and the PoC exits cleanly.

Fix

1.18 mimics the unzip binary by stripping ./.. components from each member path before extraction (File::Spec->splitdir + grep { $_ !~ /^\.\.?$/ }), so the remaining path is always confined to the destination directory instead of skipping the file.