1
0
Fork 0

Fix handling of zip bombs when unzipping archives

pull/12001/head
Jordi Boggiano 2024-05-29 15:40:58 +02:00
parent 3773f77527
commit de5f7e3241
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC
1 changed files with 24 additions and 0 deletions

View File

@ -144,6 +144,10 @@ class ZipDownloader extends ArchiveDownloader
throw $processError; throw $processError;
} }
if (str_contains($processError->getMessage(), 'zip bomb')) {
throw $processError;
}
if (!is_file($file)) { if (!is_file($file)) {
$io->writeError(' <warning>'.$processError->getMessage().'</warning>'); $io->writeError(' <warning>'.$processError->getMessage().'</warning>');
$io->writeError(' <warning>This most likely is due to a custom installer plugin not handling the returned Promise from the downloader</warning>'); $io->writeError(' <warning>This most likely is due to a custom installer plugin not handling the returned Promise from the downloader</warning>');
@ -208,6 +212,26 @@ class ZipDownloader extends ArchiveDownloader
} else { } else {
$retval = $zipArchive->open($file); $retval = $zipArchive->open($file);
} }
$totalSize = 0;
$archiveSize = filesize($file);
$totalFiles = $zipArchive->count();
if ($totalFiles > 0) {
for ($i = 0; $i < min($totalFiles, 5); $i++) {
$stat = $zipArchive->statIndex(random_int(0, $totalFiles - 1));
if ($stat === false) {
continue;
}
$totalSize += $stat['size'];
if ($stat['size'] > $stat['comp_size'] * 200) {
throw new \RuntimeException('Invalid zip file with compression ratio >99% (possible zip bomb)');
}
}
if ($archiveSize !== false && $totalSize > $archiveSize * 100 && $totalSize > 50*1024*1024) {
throw new \RuntimeException('Invalid zip file with compression ratio >99% (possible zip bomb)');
}
}
if (true === $retval) { if (true === $retval) {
$extractResult = $zipArchive->extractTo($path); $extractResult = $zipArchive->extractTo($path);