Encore mieux la bombe zip

L 'article montre comment crĂ©er une bombe zip non rĂ©cursive qui fournit un degrĂ© Ă©levĂ© de compression en chevauchant des fichiers Ă  l' intĂ©rieur d 'un conteneur zip. «Non rĂ©cursif» signifie qu'il ne dĂ©pend pas des dĂ©compresseurs dĂ©compressant les fichiers intĂ©grĂ©s dans les archives zip: il n'y a qu'un seul tour. La taille de sortie augmente de façon quadratique Ă  partir de l'entrĂ©e, atteignant un taux de compression de plus de 28 millions (10 Mo → 281 To) dans le format zip. Une extension supplĂ©mentaire est possible avec des extensions 64 bits. La conception utilise uniquement l'algorithme de compression DEFLATE le plus courant et est compatible avec la plupart des analyseurs zip.

  • zbsm.zip 42 ko → 5,5 Go
  • zblg.zip 10 Mo → 281 To
  • zbxl.zip 46 Mo → 4,5 PB (Zip64, moins compatible avec les analyseurs)

Code source:
  git clone https://www.bamsoftware.com/git/zipbomb.git 
zipbomb-20190702.zip

Données et source d'illustrations:
  git clone https://www.bamsoftware.com/git/zipbomb-paper.git 

non récursifrécursif
taille de l'archivetaille non compresséele rapporttaille non compresséele rapport
Quine Cox4404401.0∞∞
Quine Ellingsen28 80942 5691,5∞∞
42.zip42 374 *558 43213,24 507 981 343 026 016106 milliards
cette technique42 3745 461 307 620129 mille5 461 307 620129 mille
cette technique9 893 525281 395 456 244 93428 millions281 395 456 244 93428 millions
cette technique (Zip64)45 876 ​​9524 507 981 427 706 45998 millions4 507 981 427 706 45998 millions

* Il existe deux versions de 42.zip: les anciens 42 374 octets et les nouveaux 42 428 octets. La différence est que le nouveau nécessite un mot de passe avant de déballer. Nous ne comparons qu'avec l'ancienne version. Voici une copie du fichier si vous en avez besoin: 42.zip .

** Je voudrais connaßtre et indiquer l'auteur de 42.zip, mais je ne l'ai pas trouvé - faites-moi savoir si vous avez des informations.

Les bombes zip doivent surmonter le fait que l'algorithme de compression DEFLATE le plus souvent pris en charge par les analyseurs ne peut pas dĂ©passer le taux de compression de 1032 Ă  1. Pour cette raison, les bombes zip reposent gĂ©nĂ©ralement sur la dĂ©compression rĂ©cursive en insĂ©rant des fichiers zip dans des fichiers zip pour obtenir un rapport supplĂ©mentaire 1032 avec chaque couche. Mais l'astuce ne fonctionne que dans les implĂ©mentations qui dĂ©compressent rĂ©cursivement, et la plupart ne le font pas. La bombe 42.zip la plus cĂ©lĂšbre se dĂ©veloppe Ă  un formidable 4,5 PB si les six couches sont rĂ©cursivement dĂ©ballĂ©es, mais sur la couche supĂ©rieure, elle a 0,6 Mo. Les tyroliennes, comme celles de Cox et Ellingsen , donnent une copie d'eux-mĂȘmes et, par consĂ©quent, se dĂ©veloppent indĂ©finiment lors du dĂ©ballage rĂ©cursif. Mais ils sont Ă©galement complĂštement sĂ»rs lors du dĂ©ballage une fois.

Cet article montre comment crĂ©er une bombe zip non rĂ©cursive, dont le taux de compression dĂ©passe la limite DEFLATE de 1032. Il fonctionne en chevauchant les fichiers Ă  l'intĂ©rieur d'un conteneur zip pour rĂ©fĂ©rencer le «noyau» de donnĂ©es hautement compressĂ©es dans plusieurs fichiers sans faire plusieurs copies. La taille de sortie de la bombe zip croĂźt de façon quadratique par rapport Ă  la taille d'entrĂ©e; c'est-Ă -dire que le taux de compression s'amĂ©liore avec l'augmentation de la taille de la bombe. La conception dĂ©pend des fonctionnalitĂ©s de zip et DEFLATE: elle ne peut pas ĂȘtre transfĂ©rĂ©e directement vers d'autres formats de fichiers ou algorithmes de compression. La bombe est compatible avec la plupart des analyseurs zip, Ă  l'exception de ceux en "streaming", qui analysent les fichiers en une seule fois sans vĂ©rifier le rĂ©pertoire central du fichier zip. Nous essayons d'Ă©quilibrer deux objectifs contradictoires:

  • Augmentez le taux de compression. Nous dĂ©finissons le taux de compression comme la somme des tailles de tous les fichiers de l'archive divisĂ©e par la taille du fichier zip lui-mĂȘme. Il ne prend pas en compte les noms de fichiers ou autres mĂ©tadonnĂ©es de systĂšme de fichiers, mais uniquement le contenu.
  • Gardez la compatibilitĂ©. Zip est un format complexe et les analyseurs diffĂšrent, en particulier dans les situations limites, et les fonctions supplĂ©mentaires. N'utilisez pas de techniques qui fonctionnent uniquement avec certains analyseurs. Nous noterons quelques façons d'augmenter l'efficacitĂ© d'une bombe zip avec une certaine perte de compatibilitĂ©.

Structure du fichier Zip


Le fichier zip se compose d'un répertoire central de liens de fichiers.



Le rĂ©pertoire central se trouve Ă  la fin du fichier zip. Il s'agit d'une liste d'en- tĂȘtes de rĂ©pertoire central . Chaque en-tĂȘte de rĂ©pertoire central contient des mĂ©tadonnĂ©es pour un seul fichier, comme le nom de fichier et la somme de contrĂŽle CRC-32, ainsi qu'un pointeur vers l'en-tĂȘte de fichier local. L'en-tĂȘte du rĂ©pertoire central a une longueur de 46 octets plus la longueur du nom de fichier.

Le fichier se compose de l'en-tĂȘte du fichier local, suivi des donnĂ©es du fichier compressĂ©. La longueur de l'en-tĂȘte de fichier local est de 30 octets plus la longueur du nom de fichier. Il contient une copie redondante des mĂ©tadonnĂ©es de l'en-tĂȘte du rĂ©pertoire central, ainsi que les tailles des fichiers de donnĂ©es compressĂ©s et non compressĂ©s qui se trouvent derriĂšre. Zip est un format de conteneur, pas un algorithme de compression. Les donnĂ©es de chaque fichier sont compressĂ©es Ă  l'aide de l'algorithme spĂ©cifiĂ© dans les mĂ©tadonnĂ©es - gĂ©nĂ©ralement DEFLATE .

Cette description du format zip omet de nombreux détails qui ne sont pas nécessaires pour comprendre la bombe zip. Pour des informations complÚtes, voir la section 4.3 APPNOTE.TXT ou «PKZip File Structure» par Florian Buchholz, ou voir le code source .

Une redondance importante et de nombreuses ambiguïtés au format zip ouvrent des possibilités de méfaits de différents types. Une bombe zip n'est que la pointe de l'iceberg. Liens pour plus de lecture:


PremiÚre découverte: chevauchement de fichiers


En compressant une longue chaĂźne d'octets rĂ©pĂ©tĂ©s, nous pouvons crĂ©er un noyau de donnĂ©es hautement compressĂ©es. Le taux de compression du noyau lui-mĂȘme ne peut pas dĂ©passer la limite DEFLATE de 1032, nous avons donc besoin d'un moyen de rĂ©utiliser le noyau dans de nombreux fichiers, sans en crĂ©er une copie sĂ©parĂ©e dans chaque fichier. Nous pouvons le faire en chevauchant les fichiers: faites en sorte que de nombreux en-tĂȘtes du rĂ©pertoire central pointent vers un seul fichier dont les donnĂ©es sont le cƓur.



Prenons un exemple de la façon dont cette conception affecte le taux de compression. Supposons qu'un noyau de 1000 octets soit décompressé dans 1 Mo. Ensuite, le premier mégaoctet de sortie «coûte» 1078 octets de données d'entrée:

  • 31 octets pour l'en-tĂȘte du fichier local (dont 1 nom de fichier octet)
  • 47 octets pour l'en-tĂȘte du rĂ©pertoire central (y compris un nom de fichier Ă  1 octet)
  • 1000 octets par cƓur

Mais chaque 1 Mo de sortie aprĂšs le premier ne coĂ»te que 47 octets - nous n'avons pas besoin d'un autre en-tĂȘte du fichier local ou d'une autre copie du noyau, seulement d'un en-tĂȘte supplĂ©mentaire du rĂ©pertoire central. Ainsi, alors que le premier maillon du noyau a un taux de compression de 1 000 000/1 078 ≈ 928, chaque maillon supplĂ©mentaire rapproche le coefficient de 1 000 000/47 ≈ 21 277, et un gros noyau soulĂšve le plafond.

Le problĂšme avec cette idĂ©e est le manque de compatibilitĂ©. Étant donnĂ© que de nombreux en-tĂȘtes du rĂ©pertoire central pointent vers un en-tĂȘte du fichier local, les mĂ©tadonnĂ©es (en particulier, le nom du fichier) ne peuvent pas ĂȘtre les mĂȘmes pour chaque fichier. Certains analyseurs ne jurent que par cela . Par exemple, Info-ZIP UnZip (le programme de unzip standard sur Unix) rĂ©cupĂšre les fichiers, mais avec des avertissements:

  $ décompressez overlap.zip
   gonflage: A
 B: incompatibilité du nom de fichier "local" (A),
          continuer avec la version "centrale" du nom de fichier
   gonflage: B
 ... 

Le fichier zip Python lÚve également une exception :

  $ python3 -m fichier zip -e overlap.zip.
 Traceback (dernier appel le plus récent):
 ...
 __main __. BadZipFile: Le nom de fichier dans le rĂ©pertoire 'B' et l'en-tĂȘte b'A 'diffĂšrent. 

Ensuite, nous allons voir comment repenser la cohérence des noms de fichiers, tout en préservant la plupart des avantages des fichiers qui se chevauchent.

DeuxiĂšme dĂ©couverte: citer les en-tĂȘtes des fichiers locaux


Nous devons sĂ©parer les en-tĂȘtes des fichiers locaux pour chaque fichier, tout en rĂ©utilisant un noyau. La simple combinaison de tous les en-tĂȘtes ne fonctionne pas, car l'analyseur zip trouvera l'en-tĂȘte du fichier local lĂ  oĂč il attend le dĂ©but du flux DEFLATE. Mais l'idĂ©e fonctionnera, avec des changements mineurs. Nous utiliserons la fonction DEFLATE des blocs non compressĂ©s pour «citer» les en-tĂȘtes des fichiers locaux afin qu'ils semblent faire partie du mĂȘme flux DEFLATE qui se termine dans le noyau. Chaque en-tĂȘte du fichier local (sauf le premier) sera interprĂ©tĂ© de deux maniĂšres: en tant que code (partie de la structure du fichier zip) et en tant que donnĂ©es (partie du contenu du fichier).



Un flux DEFLATE est une sĂ©quence de blocs oĂč chaque bloc peut ĂȘtre compressĂ© ou non compressĂ©. Nous ne pensons gĂ©nĂ©ralement qu'aux blocs compressĂ©s, par exemple, le noyau est un gros bloc compressĂ©. Mais il existe Ă©galement des fichiers non compressĂ©s qui commencent par un en -tĂȘte de 5 octets avec un champ de longueur, ce qui signifie simplement: "affiche les n octets suivants mot pour mot." DĂ©compresser un bloc non compressĂ© signifie uniquement supprimer l'en-tĂȘte de 5 octets. Les blocs compressĂ©s et non compressĂ©s peuvent se mĂ©langer librement dans le flux DEFLATE. La sortie est une concatĂ©nation des rĂ©sultats du dĂ©ballage de tous les blocs dans l'ordre. Le concept de «non compressé» n'a d'importance qu'au niveau DEFLATE; les donnĂ©es des fichiers sont toujours considĂ©rĂ©es comme «compressĂ©es» au niveau zip, quels que soient les blocs utilisĂ©s.

La façon la plus simple d'imaginer cette conception est un chevauchement interne, du dernier fichier au premier. Nous commençons par insĂ©rer un noyau qui formera la fin du fichier de donnĂ©es pour chaque fichier. Ajoutez l'en-tĂȘte du fichier LFH N local et l'en-tĂȘte du rĂ©pertoire central CDH N qui pointe vers celui-ci. DĂ©finissez le champ de mĂ©tadonnĂ©es «taille compressĂ©e» dans LFH N et CDH N sur la taille de noyau compressĂ©. Ajoutez maintenant l'en-tĂȘte de 5 octets du bloc non compressĂ© (en vert sur le diagramme), dont le champ de longueur est Ă©gal Ă  la taille LFH N. Ajoutez le deuxiĂšme en-tĂȘte du fichier LFH local N -1 et le titre du rĂ©pertoire central CDH N -1 , qui pointe vers lui. DĂ©finissez le champ de mĂ©tadonnĂ©es «taille compressĂ©e» comme nouvel en-tĂȘte pour la taille du noyau compressĂ© plus la taille de l'en-tĂȘte de bloc non compressĂ© (5 octets) plus la taille de LFH N.

Pour le moment, le fichier zip contient deux fichiers avec les noms Y et Z. Voyons ce que l'analyseur verra lors de l'analyse. Supposons que la taille du noyau compressĂ© soit de 1000 octets et la taille LFH N de 31 octets. Nous commençons par CDH N -1 et suivons le signe pour LFH N -1 . Le nom du premier fichier est Y et la taille compressĂ©e de son fichier de donnĂ©es est de 1036 octets. En interprĂ©tant les 1036 octets suivants comme un flux DEFLATE, nous rencontrons d'abord un en-tĂȘte de 5 octets d'un bloc non compressĂ© qui dit de copier les 31 octets suivants. Nous Ă©crivons les 31 octets suivants, qui sont LFH N , que nous dĂ©compressons et ajoutons au fichier Y. En allant plus loin dans le flux DEFLATE, nous trouvons le bloc compressĂ© (noyau), que nous dĂ©compressons dans le fichier Y. Nous avons maintenant atteint la fin des donnĂ©es compressĂ©es et terminĂ© avec le fichier Y.

Passant au fichier suivant, nous suivons le pointeur de CDH N Ă  LFH N et trouvons un fichier nommĂ© Z avec une taille compressĂ©e de 1000 octets. InterprĂ©tant ces 1000 octets comme un flux DEFLATE, nous rencontrons immĂ©diatement un bloc compressĂ© (core encore) et le dĂ©compressons dans un fichier Z. Nous avons maintenant atteint la fin du fichier final et terminĂ©. Le fichier de sortie Z contient le noyau dĂ©compressĂ©; le fichier de sortie Y est le mĂȘme, mais Ă©ventuellement avec un prĂ©fixe de 31 octets LFH N.

Nous terminons la construction en rĂ©pĂ©tant la procĂ©dure de citation jusqu'Ă  ce que l'archive zip contienne le nombre de fichiers requis. Chaque nouveau fichier ajoute un en-tĂȘte de rĂ©pertoire central, un en-tĂȘte de fichier local et un bloc non compressĂ© pour citer directement Ă  partir de l'en-tĂȘte de fichier local suivant. Les donnĂ©es de fichiers compressĂ©s sont gĂ©nĂ©ralement une chaĂźne de blocs DEFLATE non compressĂ©s (en-tĂȘtes de fichiers locaux entre guillemets) suivis d'un noyau compressĂ©. Chaque octet du noyau contribue Ă  environ 1032 N Ă  la taille de sortie, car chaque octet fait partie de tous les N fichiers. Les fichiers de sortie sont Ă©galement de tailles diffĂ©rentes: les premiers sont plus grands que les derniers car ils citent davantage les en-tĂȘtes des fichiers locaux. Le contenu des fichiers de sortie n'a pas beaucoup de sens, mais personne n'a dit que cela devrait avoir du sens.

Cette conception de citation de chevauchement a une meilleure compatibilitĂ© que la conception de chevauchement complet de la section prĂ©cĂ©dente, mais la compatibilitĂ© est obtenue par compression. LĂ , chaque fichier ajoutĂ© ne coĂ»te que le titre du rĂ©pertoire central, ici il en coĂ»te le titre du rĂ©pertoire central, l'en-tĂȘte du fichier local et encore 5 octets pour l'en-tĂȘte de citation.

Optimisation


AprÚs avoir reçu le design de base de la bombe zip, nous allons essayer de la rendre aussi efficace que possible. Nous voulons répondre à deux questions:

  • Quel est le taux de compression maximal pour une taille de fichier zip donnĂ©e?
  • Quel est le taux de compression maximal compte tenu des limites du format zip?

Compression du noyau


Il est avantageux pour nous de compresser le noyau autant que possible, car chaque octet décompressé est multiplié par N. Pour cela, nous utilisons un compresseur DEFLATE personnalisé appelé bulk_deflate, spécialisé dans la compression d'une chaßne d'octets répétés.

Tous les archiveurs DEFLATE décents se rapprochent du taux de compression de 1032 sur un flux sans fin d'octets répétés, mais nous sommes préoccupés par la taille spécifique. Dans notre taille d'archive, bulk_deflate contient plus de données que les archiveurs à usage général: environ 26 Ko de plus que zlib et Info-ZIP, et environ 15 Ko de plus que Zopfli , ce qui sacrifie la vitesse au profit de la qualité de la compression.



Le prix d'un taux de compression Ă©levĂ© bulk_deflate - le manque de polyvalence. Il ne peut compresser que des lignes d'octets rĂ©pĂ©titifs et seulement une certaine longueur, Ă  savoir 517 + 258 k pour un entier k ≄ 0. En plus d'une bonne compression, bulk_deflate fonctionne rapidement, effectuant un travail presque en mĂȘme temps quelle que soit la taille des donnĂ©es d'entrĂ©e, compter le travail d'Ă©criture d'une chaĂźne compressĂ©e.

Noms de fichiers


Pour nos besoins, les noms de fichiers ont presque un poids mort. Bien qu'ils contribuent Ă  la taille de la sortie en faisant partie des en-tĂȘtes des fichiers locaux entre guillemets, les octets du nom de fichier contribuent beaucoup moins que les octets du noyau. Nous voulons que les noms de fichiers soient aussi courts que possible, tout en Ă©tant diffĂ©rents, sans oublier la compatibilitĂ©.

Chaque octet dĂ©pensĂ© sur un nom de fichier signifie deux octets non dĂ©pensĂ©s sur le noyau (deux car chaque nom de fichier apparaĂźt deux fois: dans l'en-tĂȘte du rĂ©pertoire central et dans l'en-tĂȘte du fichier local). Un octet de nom de fichier donne une moyenne de seulement ( N + 1) / 4 octets de sortie, tandis qu'un octet dans le noyau compte pour 1032 N. Exemples: 1 , 2 , 3 .

La premiĂšre considĂ©ration de compatibilitĂ© est le codage. La spĂ©cification du format zip indique que les noms de fichiers doivent ĂȘtre interprĂ©tĂ©s comme CP 437 ou UTF-8 si un bit indicateur spĂ©cifique est dĂ©fini ( APPNOTE.TXT, annexe D ). C'est le principal point d'incompatibilitĂ© entre les analyseurs zip, qui peuvent interprĂ©ter les noms de fichiers dans certains encodages fixes ou spĂ©cifiques aux paramĂštres rĂ©gionaux. Par consĂ©quent, pour des raisons de compatibilitĂ©, il est prĂ©fĂ©rable de vous limiter aux caractĂšres ayant le mĂȘme codage dans le CP 437 et l'UTF-8. À savoir, ce sont 95 caractĂšres US-ASCII imprimables.

Nous sommes également liés par des restrictions de dénomination du systÚme de fichiers. Certains systÚmes de fichiers ne sont pas sensibles à la casse, donc «a» et «A» ne sont pas considérés comme des noms différents. Les systÚmes de fichiers courants, tels que FAT32, interdisent certains caractÚres , tels que «*» et «?».

Comme compromis sûr, mais pas nécessairement optimal, notre bombe zip utilisera des noms de fichiers issus de l'alphabet à 36 caractÚres, qui n'inclut pas les caractÚres spéciaux et les caractÚres de casse différente:

  0 1 2 3 4 5 6 7 8 9 ABCDEFGHIJKLMNOPQRSTU VWXYZ 

Les noms de fichiers sont générés de maniÚre évidente, toutes les positions à tour de rÎle, avec l'ajout d'une position à la fin de la boucle:

  "0", "1", "2", ..., "Z",
 "00", "01", "02", ..., "0Z",
 ...
 "Z0", "Z1", "Z2", ..., "ZZ",
 "000", "001", "002", ... 

Il existe 36 noms de fichier Ă  un caractĂšre, 36ÂČ noms Ă  deux caractĂšres, etc. Quatre octets suffisent pour 1 727 604 noms de fichiers diffĂ©rents.

Étant donnĂ© que les noms de fichiers dans l'archive auront gĂ©nĂ©ralement des longueurs diffĂ©rentes, comment puis-je mieux les trier: du plus court au plus long ou vice versa? Si vous rĂ©flĂ©chissez un peu, il vaut mieux mettre les noms les plus longs en dernier. Ce tri ajoute plus de 900 Mo de sortie Ă  zblg.zip , par rapport Ă  la commande la plus longue Ă  la plus courte. Cependant, il s'agit d'une optimisation mineure, car 900 Mo ne reprĂ©sentent que 0,0003% de la taille totale du problĂšme.

Taille du noyau


La conception de devis qui se chevauchent vous permet de placer un noyau de données compressé, puis de le copier à plusieurs reprises à moindre coût. Pour une taille spécifique du fichier zip X , combien d'espace est optimal à allouer pour stocker le noyau, et combien pour créer des copies?

Pour trouver l'Ă©quilibre optimal, vous devez optimiser une seule variable N , le nombre de fichiers dans l'archive zip. Chaque valeur N nĂ©cessite une certaine quantitĂ© de surcharge pour les en-tĂȘtes du rĂ©pertoire central, les en-tĂȘtes des fichiers locaux, les en-tĂȘtes des blocs de citation et les noms de fichiers. Le reste de l'espace sera occupĂ© par le noyau. Étant donnĂ© que N doit ĂȘtre un entier et que vous ne pouvez mettre qu'un certain nombre de fichiers avant que la taille du noyau ne tombe Ă  zĂ©ro, il suffit de vĂ©rifier toutes les valeurs possibles de N et de sĂ©lectionner celle qui donne la plus grande sortie.

L'application de la procĂ©dure d'optimisation Ă  X = 42 374 pour 42.zip trouve un maximum Ă  N = 250. Ces 250 fichiers nĂ©cessitent 21 195 octets de surcharge, ce qui laisse 21 179 octets pour le noyau. Un noyau de cette taille est dĂ©compressĂ© en 21 841 249 octets (rapport 1031,3 pour 1). 250 copies du noyau dĂ©compressĂ© et quelques en-tĂȘtes de fichiers locaux citĂ©s donnent une sortie totale dĂ©compressĂ©e de 5 461 307 620 octets et un taux de compression de 129 000.

  zipbomb --mode = quoted_overlap --num-files = 250 --compressed-size = 21179> zbsm.zip 

L'optimisation a conduit Ă  une rĂ©partition presque uniforme de l'espace entre le noyau et les en-tĂȘtes de fichiers. Ce n'est pas un hasard. ConsidĂ©rons un modĂšle simplifiĂ© d'une construction de citation avec chevauchement. Dans un modĂšle simplifiĂ©, nous ignorons les noms de fichiers, ainsi qu'une lĂ©gĂšre augmentation de la taille du fichier de sortie en raison de la citation des en-tĂȘtes des fichiers locaux. L'analyse du modĂšle simplifiĂ© montrera que la distribution optimale entre le noyau et les en-tĂȘtes de fichier est approximativement uniforme, et la taille de sortie avec la distribution optimale croĂźt de façon quadratique en fonction de la taille de l'entrĂ©e.

Définition de certaines constantes et variables:

Xtaille du fichier zip (considéré comme fixe)
Nnombre de fichiers dans l'archive zip (variable d'optimisation)
Cdh= 46taille d'en-tĂȘte du rĂ©pertoire central (sans nom de fichier)
Lfh= 30taille de l'en-tĂȘte du fichier local (sans nom de fichier)
Q= 5DEFLATE bloc taille non compressée
C≈ 1032taux de compression du noyau

Soit H (N) le volume de la surcharge pour les en-tĂȘtes de N fichiers. Consultez le tableau pour comprendre l'essence de la formule.

H(N)=N⋅(CDH+LFH)+(N−1)⋅Q


Pour le noyau, il reste des emplacements X - H (N) . La taille totale dĂ©compressĂ©e S X (N) est Ă©gale Ă  la taille de N copies du noyau dĂ©compressĂ© avec le rapport C (dans ce modĂšle simplifiĂ©, nous ignorons la lĂ©gĂšre extension supplĂ©mentaire des en-tĂȘtes de fichiers locaux mentionnĂ©s).

$$ afficher $$ S_X (N) = (X - H (N)) CN \\ = (X - (N ⋅ (CDH + LFH) + (N - 1) ⋅ Q)) CN \\ = - - (CDH + LFH + Q) CN ^ 2 + (X + Q) CN $$ afficher $$


S X (N) est un polynĂŽme dans la partie N, par consĂ©quent, le maximum devrait ĂȘtre oĂč la dĂ©rivĂ©e S ' X (N) est Ă©gale Ă  zĂ©ro. Prendre la dĂ©rivĂ©e et trouver zĂ©ro nous donne N OPT , le nombre optimal de fichiers.

$$ afficher $$ Sâ€ČX (N_ {OPT}) = −2 (CDH + LFH + Q) C N_ {OPT} + (X + Q) C \\ 0 = −2 (CDH + LFH + Q) C N_ {OPT} + (X + Q) C \\ N_ {OPT} = (X + Q) / (CDH + LFH + Q) / 2 $$ affichage $$


H (N OPT ) donne la quantitĂ© optimale d'espace pour placer les en-tĂȘtes de fichier. Il est indĂ©pendant de CDH, LFH et C et est proche de X / 2 .

$$ afficher $$ H (N_ {OPT}) = N_ {OPT} ⋅ (CDH + LFH) + (N_ {OPT} - 1) ⋅ Q \\ = (X - Q) / 2 $$ afficher $$


S X (N OPT ) - taille totale non emballée à distribution optimale. De cela, nous voyons que la taille de la sortie augmente de façon quadratique avec l'augmentation des données d'entrée.

SX(NOPT)=(X+Q)2C/(CDH+LFH+Q)/4


En augmentant la taille du fichier zip, nous rencontrerons finalement les limites du format zip: l'archive ne peut pas avoir plus de 2 16 −1 fichiers avec une taille ne dĂ©passant pas 2 32 −1 octets chacun. Pire, certaines implĂ©mentations prennent des valeurs maximales comme indicateur de la prĂ©sence d' extensions 64 bits , donc nos limites sont en fait 2 16 -2 et 2 32 -2. Il arrive que la premiĂšre fois nous rencontrons une limite sur la taille d'un fichier non compressĂ©. Avec une taille de fichier zip de 8 319 377 octets, l'optimisation naĂŻve nous donnera le nombre de fichiers 47 837 et un fichier maximum de 2 32 +311 octets.

(En fait, tout est un peu plus compliqué, car les limites exactes dépendent de l'implémentation. Le fichier zip Python ignore le nombre de fichiers, archive / zip dans Go permet d' augmenter le nombre de fichiers jusqu'à ce qu'ils correspondent aux 16 bits inférieurs. Mais pour une compatibilité générale, nous devons respecter limites établies).

Si nous ne pouvons pas augmenter indĂ©finiment N ou la taille du noyau, nous aimerions trouver le taux de compression maximum dans le format zip. Vous devez rendre le noyau aussi grand que possible avec le nombre maximum de fichiers. MalgrĂ© le fait que nous ne pouvons plus maintenir une sĂ©paration approximativement uniforme entre le noyau et les en-tĂȘtes de fichiers, chaque fichier ajoutĂ© augmente toujours le taux de compression - mais pas aussi vite que si nous pouvions continuer Ă  augmenter le noyau. En fait, Ă  mesure que des fichiers sont ajoutĂ©s, nous devrons rĂ©duire la taille du noyau pour libĂ©rer de l'espace pour la taille de fichier maximale, qui augmente lĂ©gĂšrement avec chaque fichier ajoutĂ©.

Le plan conduit Ă  une archive zip avec 2 16 −2 fichiers et un noyau, qui est dĂ©compressĂ© en 2 32 −2 178 825 octets. Les fichiers seront plus volumineux vers le dĂ©but de l'archive zip - le premier et le plus gros fichier est dĂ©compressĂ© en 2 32 −56 octets. C'est aussi proche que possible de l'utilisation des paramĂštres de sortie approximatifs de bulk_deflate - l'encodage des 54 derniers octets coĂ»tera plus cher que leur taille (le fichier zip dans son ensemble a un taux de compression de 28 millions, et les 54 derniers octets recevront un maximum de 54 ⋅ 10 32 ⋅ ( 2 16 - 2) ≈ 36 - 5 millions d'octets, donc cela n'aide que si 54 octets peuvent ĂȘtre encodĂ©s en un octet - et je n'ai pas pu coder en moins de deux. Par consĂ©quent, si vous ne pouvez pas encoder 54 octets en 1 octet, cela ne fait que rĂ©duire le taux de compression). La taille de sortie de cette bombe zip est de 281 395 456 244 934 octets, 99,97% du maximum thĂ©orique (2 32 - 1) × (2 16 - 1). Toute amĂ©lioration significative du taux de compression ne peut ĂȘtre obtenue qu'en rĂ©duisant la taille du signal d'entrĂ©e et non en augmentant la sortie.

  zipbomb --mode = quoted_overlap --num-files = 65534 --max-uncompressed-size = 4292788525> zblg.zip 

Calcul CRC-32 efficace


Parmi les mĂ©tadonnĂ©es dans l'en-tĂȘte du rĂ©pertoire central et l'en-tĂȘte du fichier local se trouve une somme de contrĂŽle des donnĂ©es du fichier non compressĂ© - CRC-32 . Cela pose un problĂšme car la quantitĂ© de calculs CRC-32 pour chaque fichier est proportionnelle Ă  sa taille, qui est trĂšs grande par dĂ©faut (aprĂšs tout, c'est une bombe zip). Nous prĂ©fĂ©rons effectuer un travail au moins proportionnel Ă  la taille de l'archive. Deux facteurs jouent en notre faveur: tous les fichiers ont un noyau commun et un noyau non compressĂ© est une chaĂźne d'octets rĂ©pĂ©tĂ©s. Imaginez le CRC-32 comme un produit matriciel - cela nous permettra non seulement de calculer rapidement la somme de contrĂŽle du noyau, mais Ă©galement de rĂ©utiliser les calculs entre les fichiers. La mĂ©thode dĂ©crite dans cette section est une petite extension de la fonction crc32_combine dans zlib, que Mark Adler explique ici .

Le CRC-32 peut ĂȘtre modĂ©lisĂ© comme une machine d'Ă©tat, mettant Ă  jour un registre d'Ă©tat 32 bits pour chaque bit d'entrĂ©e. Les opĂ©rations de mise Ă  jour de base pour les bits 0 et 1 sont les suivantes:

 uint32 crc32_update_0(uint32 state) { // Shift out the least significant bit. bit b = state & 1; state = state >> 1; // If the shifted-out bit was 1, XOR with the CRC-32 constant. if (b == 1) state = state ^ 0xedb88320; return state; } uint32 crc32_update_1(uint32 state) { // Do as for a 0 bit, then XOR with the CRC-32 constant. return crc32_update_0(state) ^ 0xedb88320; } 

Si vous reprĂ©sentez le registre d'Ă©tat comme un vecteur binaire Ă  32 Ă©lĂ©ments et utilisez XOR pour l'addition et la multiplication, alors crc32_update_0 est un mappage linĂ©aire ; c'est-Ă -dire qu'il peut ĂȘtre reprĂ©sentĂ© comme une multiplication par une matrice de transition binaire 32 × 32. Pour comprendre pourquoi, notez que multiplier une matrice par un vecteur revient simplement Ă  additionner les colonnes de la matrice aprĂšs avoir multipliĂ© chaque colonne par l'Ă©lĂ©ment correspondant du vecteur. L' state >> 1 opĂ©ration de dĂ©calage state >> 1 prend simplement chaque bit i du vecteur d'Ă©tat et le multiplie par un vecteur qui est nul partout sauf pour le bit i - 1 (numĂ©rotation des bits de droite Ă  gauche). Relativement parlant, l' state ^ 0xedb88320 XOR final state ^ 0xedb88320 se produit uniquement lorsque le bit b est Ă©gal Ă  un. Cela peut ĂȘtre reprĂ©sentĂ© comme la premiĂšre multiplication de b par 0xedb88320, puis XORing Ă  cet Ă©tat.

De plus, crc32_update_1 n'est qu'une crc32_update_0 plus (XOR).Cela fait crc32_update_1 une transformation affine : multiplication matricielle suivie d'une cartographie (c'est-Ă -dire, addition de vecteur). Nous pouvons imaginer la multiplication et la cartographie matricielles en une seule Ă©tape, si nous augmentons la taille de la matrice de transformation Ă  33 × 33 et ajoutons un Ă©lĂ©ment supplĂ©mentaire au vecteur d'Ă©tat, qui est toujours 1 (cette reprĂ©sentation est appelĂ©e coordonnĂ©es homogĂšnes ).


Les matrices de transformation sont 33 × 33 M 0 et M 1 , qui calculent le changement d'Ă©tat CRC-32 effectuĂ© respectivement par les bits 0 et 1. Les vecteurs de colonne sont stockĂ©s avec le bit le plus significatif ci-dessous: en lisant la premiĂšre colonne de bas en haut, vous voyez la constante polynomiale CRC-32 edb8832016 = 111 0 11 0 110 111 000 1 00000 11 00 1 00000 2 . Ces deux matrices ne diffĂšrent que dans la derniĂšre colonne, qui reprĂ©sente le vecteur de translation en coordonnĂ©es homogĂšnes. Dans M 0, la translation est nulle et dans M 1, c'est edb88320 16 , la constante polynomiale est CRC-32. Les unitĂ©s sont immĂ©diatement au-dessus de l'Ă©tat de l'opĂ©ration en diagonalestate >> 1

deux opĂ©rationscrc32_update_0etcrc32_update_1peuvent ĂȘtre reprĂ©sentĂ©s par la matrice de transition de 33 x 33. Les matrices M 0 et M 1 sont reprĂ©sentĂ©es.. L'avantage de la reprĂ©sentation matricielle est que les matrices peuvent ĂȘtre multipliĂ©es. Supposons que nous voulons voir un changement d'Ă©tat effectuĂ© en traitant un caractĂšre ASCII «a», dont la reprĂ©sentation binaire est 01100001 2 . On peut imaginer le changement cumulĂ© de l'Ă©tat du CRC-32 de ces huit bits dans une matrice de transformation:

M a = M 0 M 1 M 1 M 0 M 0 M 0 M 0 M 1


Et nous pouvons imaginer un changement dans l'état d'une rangée répétant «a» en multipliant plusieurs copies de M a - élevant la matrice à une puissance. Nous pouvons le faire rapidement en utilisant l' algorithme d'exponentiation rapide , ce qui permet de calculer le M n connectez 2 n étapes. Par exemple, voici une matrice pour changer l'état d'une chaßne de 9 caractÚres 'a':

( M a ) 9 = M a M a M a M a M a M a M a M a M a M a M a=(MaMaMaMa)2Ma=((MaMa)2)2Ma=(((Ma)2)2)2Ma


L'algorithme de multiplication rapide de matrice est utile pour calculer le noyau M , une matrice pour un noyau non compressĂ©, car le noyau est une chaĂźne d'octets rĂ©pĂ©tĂ©s. Pour obtenir la somme de contrĂŽle CRC-32 de la matrice, multipliez la matrice par le vecteur zĂ©ro (le vecteur zĂ©ro est en coordonnĂ©es uniformes, soit 32 zĂ©ros, puis l'unitĂ©; ici, nous omettons la lĂ©gĂšre complication du prĂ© et post-traitement de la somme de contrĂŽle pour vĂ©rifier la conformitĂ©). Pour calculer la somme de contrĂŽle de chaque fichier, nous travaillons dans la direction opposĂ©e. Nous commençons par un initialisĂ©es M: M = le noyau . La somme de contrĂŽle du noyau est Ă©galement la somme de contrĂŽle du fichier final N , donc nous multiplions Mun vecteur zĂ©ro et stocke la somme de contrĂŽle reçue dans la CDH N et LFH N . Les donnĂ©es du fichier N - 1 sont les mĂȘmes que les donnĂ©es du fichier N , mais avec le prĂ©fixe LFH N ajoutĂ© . Par consĂ©quent, nous calculonsM L F H N , matrice de changement d'Ă©tat pour LFHNet mise Ă  jourM : = M M L F H N .Maintenant, M reprĂ©sente le changement d'Ă©tat cumulatif du traitement de LFH N derriĂšre le noyau. Nous calculons la somme de contrĂŽle pour le fichier N - 1 , multipliant Ă  nouveau M par le vecteur zĂ©ro. Nous continuons la procĂ©dure en accumulant des matrices de changement d'Ă©tat dans M jusqu'Ă  ce que tous les fichiers soient traitĂ©s.

Extension: Zip64


Plus tĂŽt, nous avons Ă©tĂ© confrontĂ©s au problĂšme de l'expansion en raison des limitations du format zip - il Ă©tait impossible d'Ă©mettre plus de 281 To, quelle que soit la façon dont le fichier zip Ă©tait emballĂ©. Vous pouvez transcender ces limites en utilisant Zip64, une extension au format zip qui augmente la taille de certains champs d'en-tĂȘte Ă  64 bits. La prise en charge de Zip64 n'est en aucun cas universelle, mais c'est l'une des extensions les plus couramment implĂ©mentĂ©es. Quant au taux de compression, l'effet de Zip64 est d'augmenter la taille de l'en-tĂȘte du rĂ©pertoire central de 46 Ă  58 octets, et la taille de l'en-tĂȘte du rĂ©pertoire local de 30 Ă  50 octets. En regardant la formule du coefficient d'expansion optimal dans un modĂšle simplifiĂ©, nous voyons que la bombe zip au format Zip64 croĂźt toujours de maniĂšre quadratique, mais plus lentement en raison du plus grand dĂ©nominateur - cela peut ĂȘtre vu dans le diagramme ci-dessous. En raison de la perte de compatibilitĂ© et du retard de croissance, nous supprimons presque toutes les restrictions sur la taille des fichiers.

Supposons que nous ayons besoin d'une bombe zip qui se dĂ©veloppe Ă  4,5 PB, comme 42.zip. Quelle doit ĂȘtre la taille des archives? En utilisant la recherche binaire, nous constatons que la taille minimale d'un tel fichier est de 46 Mo.

  • zbxl.zip 46 Mo → 4,5 PB (Zip64, moins compatible)
 zipbomb --mode = quoted_overlap --num-files = 190023 --compressed-size = 22982788 --zip64> zbxl.zip 

4,5 pĂ©taoctets - Ă  peu prĂšs la mĂȘme quantitĂ© de donnĂ©es a Ă©tĂ© enregistrĂ©e par le tĂ©lescope Event Horizon pour la premiĂšre image d'un trou noir : des racks et des racks avec des disques durs dans le centre de donnĂ©es.

Avec Zip64, il n'est presque pas intĂ©ressant de considĂ©rer le taux de compression maximal, car nous pouvons simplement continuer Ă  augmenter la taille du fichier zip et le taux de compression avec lui, jusqu'Ă  ce que mĂȘme le fichier zip compressĂ© devienne prohibitif. Un seuil intĂ©ressant, cependant, est de 2 64 octets (18 EB ou 16 EiB) - tant de donnĂ©es ne rentreront pas sur la plupart des systĂšmes de fichiers. La recherche binaire trouve la plus petite bombe zip qui produit au moins autant de sortie: elle contient 12 millions de fichiers et un noyau compressĂ© de 1,5 Go. La taille totale du fichier zip est de 2,9 Go et il est dĂ©ballĂ© en 2 64+11 727 895 877 octets avec un taux de compression de plus de 6,2 milliards Ă  un. Je n'ai pas tĂ©lĂ©chargĂ© ce fichier pour le tĂ©lĂ©charger, mais vous pouvez le gĂ©nĂ©rer vous-mĂȘme en utilisant le code source . Il a des fichiers d'une taille telle que mĂȘme un bug a Ă©tĂ© rĂ©vĂ©lĂ© dans Info-ZIP UnZip 6.0.

 zipbomb --mode = quoted_overlap --num-files = 12056313 --compressed-size = 1482284040 --zip64> zbxxl.zip 

Extension: bzip2


DEFLATE est l'algorithme de compression le plus courant pour le format zip, mais ce n'est qu'une des nombreuses options. Le deuxiÚme algorithme le plus courant est probablement bzip2 . Bien qu'il ne soit pas aussi compatible que DEFLATE. Théoriquement, dans bzip2, le taux de compression maximal est d'environ 1,4 million pour un, ce qui permet un compactage plus dense du noyau.

bzip2 code d'abord le «codage de longueur d'exĂ©cution», rĂ©duisant de 51 fois la longueur de chaĂźne des octets rĂ©pĂ©tĂ©s. Ensuite, les donnĂ©es sont divisĂ©es en blocs de 900 Ko et chaque bloc est compressĂ© sĂ©parĂ©ment. ThĂ©oriquement, un bloc peut compresser jusqu'Ă  32 octets. 900 000 × 51/32 = 1 434 375.

Ignorant la perte de compatibilité, bzip2 fait-il une bombe plus efficace?

Oui - mais uniquement pour les petits fichiers. Le problĂšme est que dans bzip2 il n'y a rien de tel que les blocs DEFLATE non compressĂ©s que nous avons utilisĂ©s pour citer les en-tĂȘtes des fichiers locaux. Ainsi, il est impossible de chevaucher des fichiers et de rĂ©utiliser le noyau - pour chaque fichier, vous devez Ă©crire votre propre copie, donc le taux de compression global ne sera pas meilleur que le taux pour un seul fichier. Dans le graphique ci-dessous, nous voyons que sans chevauchement, bzip2 est supĂ©rieur Ă  DEFLATE uniquement pour les fichiers d'environ mĂ©gaoctets.

Il n'y a qu'un espoir pour un autre moyen de citer les en-tĂȘtes dans bzip2, qui est discutĂ© dans la section suivante. De plus, si vous savez qu'un analyseur zip particulier prend en charge bzip2 etpermet des noms de fichiers incompatibles, vous pouvez utiliser la construction de chevauchement complĂšte, qui n'a pas besoin d'ĂȘtre citĂ©e.


Comparaison du taux de compression de diffĂ©rentes bombes zip. Faites attention Ă  l'axe logarithmique. Chaque design est illustrĂ© avec et sans Zip64. Les structures sans chevauchement ont un taux de croissance linĂ©aire, qui peut ĂȘtre vu Ă  partir du rapport constant des axes. Le dĂ©calage vertical du graphique bzip2 signifie que le taux de compression de bzip2 est environ mille fois supĂ©rieur Ă  celui de DEFLATE. Les constructions DEFLATE citĂ©es ont un taux de croissance quadratique, comme en tĂ©moigne une inclinaison vers les axes 2: 1. La variante Zip64 est lĂ©gĂšrement moins efficace, mais permet plus de 281 To. Les graphiques pour bzip2 avec des citations Ă  travers un champ supplĂ©mentaire passent de quadratique Ă  linĂ©aire lorsque la taille maximale du fichier est atteinte (2 32 −2 octets), ou le nombre maximal autorisĂ© de fichiers

Extension: cotation via un champ supplémentaire


Jusqu'Ă  prĂ©sent, nous avons utilisĂ© la fonction DEFLATE pour citer les en-tĂȘtes des fichiers locaux, et nous venons de voir que cette astuce ne fonctionne pas dans bzip2. Cependant, il existe une autre mĂ©thode de citation, un peu plus limitĂ©e, qui n'utilise que des fonctions de format zip et est indĂ©pendante de l'algorithme de compression.

À la fin de la structure d'en-tĂȘte du fichier local, il y a un champ supplĂ©mentaire de longueur variable pour stocker des informations qui ne correspondent pas aux champs d'en-tĂȘte habituels ( APPNOTE.TXT, section 4.3.7) Des informations supplĂ©mentaires peuvent inclure, par exemple, un horodatage ou un uid / gid d'Unix. Les informations Zip64 sont Ă©galement stockĂ©es dans un champ supplĂ©mentaire. Un champ supplĂ©mentaire est reprĂ©sentĂ© comme une structure de valeur de longueur; si vous augmentez la longueur sans ajouter de valeur, le champ supplĂ©mentaire inclura ce qu'il y a derriĂšre dans le fichier zip, Ă  savoir l'en-tĂȘte suivant du fichier local. En utilisant cette mĂ©thode, chaque en-tĂȘte du fichier local peut «citer» les en-tĂȘtes suivants, en les enfermant dans son propre champ supplĂ©mentaire. ComparĂ© Ă  DEFLATE, il y a trois avantages:

  1. Citer via un champ supplémentaire ne nécessite que 4 octets, pas 5, ce qui laisse plus d'espace pour le noyau.
  2. Il n'augmente pas la taille du fichier, ce qui signifie un noyau plus grand, compte tenu des limites du format zip.
  3. Il fournit des citations dans bzip2.

MalgrĂ© ces avantages, la cotation dans des champs supplĂ©mentaires est moins flexible. Ce n'est pas une chaĂźne, comme dans DEFLATE: chaque en-tĂȘte d'un fichier local doit contenir non seulement l'en-tĂȘte immĂ©diatement suivant, mais aussi tous les en-tĂȘtes suivants. Les champs supplĂ©mentaires augmentent Ă  mesure que vous approchez du dĂ©but du fichier zip. Étant donnĂ© que la longueur maximale du champ est de 2 16 −1 octets, seuls 1808 en-tĂȘtes de fichiers locaux (ou 1170 en Zip64) peuvent ĂȘtre citĂ©s, en supposant que les noms sont attribuĂ©s comme prĂ©vu.(dans le cas de DEFLATE, vous pouvez utiliser un champ supplĂ©mentaire pour citer les premiers en-tĂȘtes (les plus courts) des fichiers locaux, puis passer Ă  la citation DEFLATE pour le reste). Autre problĂšme: pour correspondre Ă  la structure interne des donnĂ©es du champ supplĂ©mentaire, il est nĂ©cessaire de sĂ©lectionner une balise 16 bits pour le type ( APPNOTE.TXT, section 4.5.2 ) prĂ©cĂ©dant les donnĂ©es de citation. Nous voulons sĂ©lectionner une balise de type qui obligera les analyseurs Ă  ignorer les donnĂ©es entre guillemets, plutĂŽt que d'essayer de les interprĂ©ter comme des mĂ©tadonnĂ©es significatives. Les analyseurs Zip devraient ignorer les balises de type inconnu, afin que nous puissions sĂ©lectionner des balises au hasard, mais il y a un risque qu'Ă  l'avenir certaines balises violent la compatibilitĂ© du design.

Le schĂ©ma prĂ©cĂ©dent illustre la possibilitĂ© d'utiliser des champs supplĂ©mentaires dans bzip2, c et sans Zip64. Sur les deux graphiques, il y a un tournant, lorsque la croissance passe du quadratique au linĂ©aire. Sans Zip64, cela se produit lorsque la taille maximale du fichier non compressĂ© est atteinte (2 32−2 octets); alors vous pouvez seulement augmenter le nombre de fichiers, mais pas leur taille. Le graphique se termine complĂštement lorsque le nombre de fichiers atteint 1809, puis nous manquons d'espace dans un champ supplĂ©mentaire pour citer des en-tĂȘtes supplĂ©mentaires. Avec Zip64, une fracture se produit sur 1171 fichiers, aprĂšs quoi seule la taille du fichier peut ĂȘtre augmentĂ©e, mais pas leur nombre. Un champ supplĂ©mentaire aide dans le cas de DEFLATE, mais la diffĂ©rence est si petite qu'elle n'est pas visuellement perceptible. Il augmente le taux de compression de zbsm.zip de 1,2%; zblg.zip de 0,019%; et zbxl.zip de 0,0025%.

La discussion


Dans leur travail sur ce sujet, Pletz et ses collĂšgues utilisent le chevauchement de fichiers pour crĂ©er une archive zip presque auto-rĂ©plicable. Le chevauchement du fichier lui-mĂȘme a Ă©tĂ© suggĂ©rĂ© plus tĂŽt (diapositive 47) par Ginvael Coldwind.

Nous avons dĂ©veloppĂ© une conception d'une bombe zip avec un chevauchement de devis prenant en compte la compatibilitĂ© - un certain nombre de diffĂ©rences dans les implĂ©mentations, dont certaines sont prĂ©sentĂ©es dans le tableau ci-dessous. La conception rĂ©sultante est compatible avec les analyseurs zip qui fonctionnent de la maniĂšre habituelle, c'est-Ă -dire en vĂ©rifiant d'abord le rĂ©pertoire central et en l'utilisant comme index de fichiers. Parmi eux, un analyseur zip unique de Nailqui est gĂ©nĂ©rĂ© automatiquement Ă  partir de la grammaire formelle. Cependant, la conception est incompatible avec les analyseurs "en streaming", qui analysent le fichier zip du dĂ©but Ă  la fin en une seule passe sans avoir d'abord lu le rĂ©pertoire central. De par leur nature, les analyseurs en streaming ne permettent en aucun cas aux fichiers de se chevaucher. TrĂšs probablement, ils extrairont uniquement le premier fichier. De plus, ils peuvent mĂȘme lancer une erreur, comme c'est le cas avec sunzip , qui analyse le rĂ©pertoire central Ă  la fin et vĂ©rifie la cohĂ©rence avec les en-tĂȘtes des fichiers locaux qu'il a dĂ©jĂ  vus.

Si vous souhaitez que les fichiers extraits commencent par un prĂ©fixe spĂ©cifique diffĂ©rent des octets d'en-tĂȘte du fichier local, vous pouvez insĂ©rer un bloc DEFLATE avant le bloc non compressĂ© citĂ© par l'en-tĂȘte suivant. Tous les fichiers de l'archive zip ne doivent pas participer Ă  la crĂ©ation de la bombe: vous pouvez inclure des fichiers ordinaires dans l'archive, si nĂ©cessaire, afin de correspondre Ă  un format spĂ©cial (il y a un paramĂštre dans le code source --templatepour ce cas d'utilisation). De nombreux formats utilisent zip comme conteneur, tels que les documents Java JAR, Android APK et LibreOffice.

PdfĂ  bien des Ă©gards similaire Ă  zip. Il a une table de rĂ©fĂ©rences croisĂ©es Ă  la fin du fichier qui pointe vers les objets prĂ©cĂ©dents, et il prend en charge la compression des objets via le filtre FlateDecode. Je n'ai pas essayĂ©, mais vous pouvez utiliser l'idĂ©e de citer avec chevauchement pour fabriquer une bombe PDF. Peut-ĂȘtre que vous n'avez mĂȘme pas Ă  travailler dur ici: binaryhax0r Ă©crit dans un article de blog que vous pouvez simplement spĂ©cifier plusieurs couches FlateDecode sur un objet, aprĂšs quoi la crĂ©ation d'une bombe PDF devient triviale.

DĂ©finir une classe particuliĂšre de bombes zip dĂ©crit dans cet article est simple: il suffit de trouver les fichiers qui se chevauchent. Mark Adler a Ă©crit un patchpour Unzip Info-ZIP, qui fait exactement cela. Cependant, en gĂ©nĂ©ral, le blocage des fichiers qui se chevauchent ne protĂšge pas contre toutes les classes de bombes zip. Il est difficile de prĂ©dire Ă  l'avance si le fichier est une bombe zip ou non si vous n'avez pas une connaissance prĂ©cise des composants internes des analyseurs qui seront utilisĂ©s pour l'analyser. La consultation des en-tĂȘtes et la somme des champs «taille non compressĂ©e» de tous les fichiers ne fonctionnent pas , car la valeur dans les en-tĂȘtes peut ne pas correspondre Ă  la taille rĂ©elle non compressĂ©e (dans le tableau de compatibilitĂ©, voir la ligne «permet que le fichier soit trop petit»). Une protection fiable contre les bombes zip comprend des limites de temps, de mĂ©moire et d'espace disque dans l'analyseur zip pendant son fonctionnement. Prenez l'analyse des fichiers zip, comme toutes les opĂ©rations complexes avec des donnĂ©es non fiables, avec prudence.


zip-, , zip-. DEFLATE Zip64, , CRC 32- 16- .

Remerciements


Merci à Mark Adler , Russ Cox , Brandon Enright , Marek Maykovsky , Josh Wolfe et aux critiques de USENIX WOOT 2019 pour leurs commentaires sur le projet de cet article. Kaolan McNamara a évalué l'impact des bombes zip sur la sécurité de LibreOffice.

Une version de cet article a été préparée pour l'atelier USENIX WOOT 2019 . Le code source est disponible. Les artefacts à présenter lors de l'atelier se trouvent dans le fichier zipbomb-woot19.zip .

Avez-vous trouvé un systÚme qui largue l'une des bombes? Les bombes vous ont-elles aidé à trouver un bug ou à gagner de l'argent dans un programme de recherche de bug? Faites le moi savoir, je vais essayer de le mentionner ici.

LibreOffice 6.1.5.2


AprÚs avoir renommé zblg.zip en zblg.odt ou zblg.docx, LibreOffice crée et supprime une série de fichiers temporaires d'environ 4 Go, essayant de déterminer le format de fichier. En fin de compte, il termine cette opération et supprime les fichiers temporaires à mesure qu'ils arrivent, de sorte que la bombe zip ne provoque qu'un DoS temporaire sans remplir le disque. Kaolan McNamara a répondu à mon message d'erreur.

Mozilla addons-server 2019.06.06


J'ai essayĂ© des bombes zip contre l'installation du serveur d'addons local, qui fait partie du logiciel addons.mozilla.org. Le systĂšme gĂšre gracieusement la bombe, imposant un dĂ©lai de 110 secondes sur l'extraction des fichiers. La bombe zip se dĂ©veloppe rapidement, dans la mesure oĂč le disque le permet jusqu'Ă  cette limite de temps, mais le processus est alors tuĂ© et les fichiers dĂ©compressĂ©s sont finalement automatiquement effacĂ©s.

UnZip 6.0


Mark Adler a écrit un patch pour UnZip pour détecter cette classe de bombes zip.

5 juillet 2019: j'ai remarquĂ© que CVE-2019-13232 a Ă©tĂ© attribuĂ© Ă  UnZip. Personnellement, je dirais que la capacitĂ© / l'incapacitĂ© d'UnZip (ou de tout analyseur zip) de traiter ce type de bombe zip est nĂ©cessairement une vulnĂ©rabilitĂ© ou mĂȘme un bug. Il s'agit d'une implĂ©mentation naturelle qui ne viole pas les spĂ©cifications, que puis-je dire. Le type de bombe dans cet article n'est qu'un type, et il existe de nombreuses autres façons de rĂ©soudre un analyseur zip. Comme mentionnĂ© ci-dessus, si vous souhaitez vous protĂ©ger contre les attaques d'Ă©puisement des ressources, vous ne devez pas essayer de rĂ©pertorier, dĂ©tecter et bloquer chaque attaque connue; il est plutĂŽt nĂ©cessaire d'Ă©tablir des restrictions externes sur le temps et les autres ressources afin que l'analyseur n'entre pas dans une telle situation, quel que soit le type d'attaque qu'il a rencontrĂ©. Il n'y a rien de mal Ă  essayer de dĂ©tecter et de rejeter certains modĂšles comme une optimisation de la premiĂšre passe,mais vous ne pouvez pas vous arrĂȘter lĂ . À moins que vous finissiez par isoler et restreindre les opĂ©rations avec des donnĂ©es non fiables, votre systĂšme est probablement toujours vulnĂ©rable. ConsidĂ©rez l'analogie avec les scripts intersites en HTML: la bonne protection n'est pas d'essayer de filtrer des octets spĂ©cifiques qui peuvent ĂȘtre interprĂ©tĂ©s comme du code, mais d'Ă©viter tout correctement.

Moteurs antivirus


L'utilisateur de Twitter @TVqQAAMAAAAEAAA rapporte : "L'antivirus McAfee sur ma machine de test vient d'exploser." Je ne l'ai pas testĂ© moi-mĂȘme et je n'ai pas de dĂ©tails tels que le numĂ©ro de version.

Tavis Ormandi indique que VirusTotal a un certain nombre de dĂ©lais d'expiration pour zblg.zip ( capture d'Ă©cran du 6 juin 2019 ): AhnLab-V3, ClamAV, DrWeb, Endgame, F-Secure, GData, K7AntiVirus, K7GW, MaxSecure, McAfee, McAfee-GW -Edition, Panda, Qihoo-360, Sophos ML, VBA32. RĂ©sultats pour zbsm.zip ( capture d'Ă©cran du 6 juin 2019) sont similaires, mais avec un ensemble diffĂ©rent de moteurs de temporisation: Baido, Bkav, ClamAV, CMC, DrWeb, Endgame, ESET-NOD32, F-Secure, GData, Kingsoft, McAfee-GW-Edition, NANO-Antivirus, Acronis. Fait intĂ©ressant, il n'y a pas de dĂ©lais d'attente dans les rĂ©sultats de zbxl.zip ( capture d'Ă©cran du 6 juin 2019 ). Peut-ĂȘtre que certains antivirus ne prennent pas en charge Zip64? Plusieurs moteurs dĂ©tectent les fichiers comme une sorte de «bombe de compression». Il est intĂ©ressant de voir s'ils continueront Ă  le faire avec des modifications mineures, telles que la modification des noms de fichiers ou l'ajout d'un prĂ©fixe ASCII Ă  chaque fichier.

Déclaration finale


Il est temps de mettre fin Ă  Facebook. Ce n'est pas un travail neutre pour vous: chaque jour, quand vous venez au travail, vous faites quelque chose de mal. Si vous avez un compte Facebook, supprimez-le. Si vous travaillez sur Facebook, licenciez-vous.

Et n'oubliez pas que l'Agence de sĂ©curitĂ© nationale doit ĂȘtre dĂ©truite.

Source: https://habr.com/ru/post/fr459254/


All Articles