
Hash collisions and exploitations
Di Ange Albertini e Marc Stevens.
D: È possibile fare in modo che un file ottenga un MD2/MD4/MD5/MD6/SHA1/SHA2/SHA3 arbitrario, o lo stesso hash di un altro file?
R: No.
D: Si possono creare 2 file diversi con lo stesso hash?
R: Con MD5, in pochi secondi su un computer standard. Con SHA1, è possibile ma non pratico per gli utenti finali (Complessità: 2^61.2 Prezzo: $11k).
D: Si può fare in modo che 2 file diversi ottengano lo stesso hash aggiungendo dati?
R: Con MD5, in poche ore su un computer standard. Con SHA1, è possibile ma non pratico per gli utenti finali (Complessità: 2^63.4 Prezzo: $45K)
D: I 2 file rimarranno validi?
R: In generale, sì, poiché la maggior parte dei formati di file tollera dati aggiunti. D'altra parte, le firme dei file saranno probabilmente rotte.
D: Si possono creare 2 file diversi con contenuti arbitrari e lo stesso hash?
R: Sì, può essere immediato facendo affidamento su strutture di file speciali:
D: Per quali formati posso ottenere una coppia di file con collisione MD5 istantanea?
R: JPG, PNG, GIF, GZIP, Portable Executable, MP4, JPEG2000, PDF, DOCX/PPTX/XSLX, EPUB, 3MF, XPS. Basta eseguire lo script specifico.
D: E per SHA1?
R: Per SHA1, JPG in un PDF è calcolato e implementato.
D: E i formati già supportati per MD5 (JPG, PNG...), ma per SHA1?
R: È molto probabile che siano supportati anche con SHA1, ma le loro collisioni non sono state calcolate.
D: I calcoli sono più veloci per contenuti simili (ma diversi)?
R: No. Qualsiasi minima differenza richiede un calcolo completo.
D: Quali formati non hanno questa scorciatoia?
R: ELF, Mach-O, Java Class, TAR, ZIP (tra gli altri...)
D: Le collisioni classiche (in poche ore) sono ancora possibili con questi formati?
R: Sì, purché venga tollerata qualsiasi quantità di dati aggiunti (cioè probabilmente non ZIP o Class).
D: Fornite esempi di collisioni?
R: Sì.
L'obiettivo è esplorare a fondo gli attacchi esistenti - e mostrare lungo il percorso quanto sia debole MD5 (collisioni istantanee di qualsiasi JPG, PNG, PDF, MP4, PE...) - e anche esplorare in dettaglio i formati di file comuni per determinare come possono essere sfruttati con attacchi presenti o futuri.
In effetti, lo stesso trucco del formato di file può essere usato su più hash (gli stessi trucchi JPG sono stati usati per MD5, malicious SHA-1 e SHA1), purché le collisioni seguano gli stessi pattern di byte.
Questo documento non riguarda nuovi attacchi (il più recente è stato documentato nel 2012), ma nuove forme di sfruttamento degli attacchi esistenti.
Stato attuale degli attacchi noti:
ottenere che un file abbia l'hash di un altro file o un hash dato: impossibile
ottenere due file diversi con lo stesso MD5: istantaneo
far ottenere a due file arbitrari lo stesso MD5: poche ore (72 ore.core)
far ottenere a due file arbitrari di formati di file specifici (PNG, JPG, PE...) lo stesso MD5: istantaneo
ottenere due file diversi con lo stesso SHA1: 6500 anni.core
(*) esempio con crypt - grazie Sven!```
import crypt crypt.crypt("5dUD&66", "br") 'brokenOz4KxMc' crypt.crypt("O!>',%$", "br") 'brokenOz4KxMc'
# Attacchi
MD5 e SHA1 lavorano con blocchi di 64 byte.
Se due contenuti A e B hanno lo stesso hash, allora aggiungendo lo stesso contenuto C a entrambi, l'hash rimarrà lo stesso.``` text
hash(A) = hash(B) -> hash(A + C) = hash(B + C)
Le collisioni funzionano inserendo, al confine di un blocco, un numero di blocchi di collisione calcolati che dipende da ciò che viene prima nel file. Questi blocchi di collisione hanno un aspetto molto casuale con alcune piccole differenze (che seguono uno schema specifico per ogni attacco) e introdurranno piccole differenze mentre alla fine porteranno gli hash allo stesso valore dopo questi blocchi.
Queste differenze vengono sfruttate per creare file validi con proprietà specifiche.
Anche i formati di file lavorano dall'alto verso il basso e la maggior parte di essi funziona tramite chunk a livello di byte.
Alcuni chunk 'commento' possono essere inseriti per allineare i chunk del file ai confini di blocco, per allineare strutture specifiche alle differenze dei blocchi di collisione, per nascondere il resto della casualità dei blocchi di collisione ai parser del file, e per nascondere contenuti altrimenti validi al parser (così che veda un altro contenuto).
Questi chunk 'commento' spesso non sono commenti ufficialmente reali: sono solo usati come contenitori di dati ignorati dal parser (ad esempio, i chunk PNG con ID che inizia con una lettera minuscola sono ancillari, non critici).
Nella maggior parte dei casi, una differenza nei blocchi di collisione viene usata per modificare la lunghezza di un chunk di commento,
che tipicamente viene dichiarato subito prima dei dati di questo chunk:
nello spazio tra la versione più corta e quella più lunga di questo chunk,
viene dichiarato un altro chunk di commento per saltare oltre il contenuto A di un file.
Dopo questo contenuto di file A, basta aggiungere un altro contenuto di file B.

Poiché i formati di file di solito definiscono un terminatore che farà fermare i parser dopo di esso,
A terminerà il parsing, il che farà sì che il contenuto aggiunto B venga ignorato.
Quindi tipicamente servono almeno due commenti - spesso tre:
Queste proprietà comuni dei formati di file rendono possibile tutto ciò - non sono tipicamente viste come debolezze, ma possono essere rilevate o normalizzate:
| Prefisso | = | Prefisso |
|---|---|---|
| Collisione A | ≠ | Collisione B |
| Suffisso | = | Suffisso |
Entrambi i file sono quasi identici (i loro contenuti hanno solo pochi bit di differenze)
Sfruttamento:
Raggruppa due contenuti, poi:
Due file con questa struttura:
mostreranno o A o B.
Versione finale nel 2009.
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
.. .. .. .X. .. .. .. .. .. .. .. .. .. .. .. ..
.. .. .. .. .. .. .. .. .. .. .. .. .. .X. .. ..
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Le differenze non sono vicine all'inizio/fine dei blocchi, quindi è molto difficile da sfruttare poiché non controlli alcun byte vicino. Una soluzione potenziale è forzare i byte circostanti - cfr PoCGTFO 14:10.
Esempi:
Con un prefisso vuoto:``` MD5: fe6c446ee3a831ee010f33ac9c1b602c SHA256: c5dd2ef7c74cd2e80a0fd16f1dd6955c626b59def888be734219d48da6b9dbdd
00: 37 75 C1 F1-C4 A7 5A E7-9C E0 DE 7A-5B 10 80 26 7u┴±─ºZτ£α▐z[►Ç&
10: 02 AB D9 39-C9 6C 5F 02-12 C2 7F DA-CD 0D A3 B0 ☻½┘9╔l_☻↕┬⌂┌═♪ú░
20: 8C ED FA F3-E1 A3 FD B4-EF 09 E7 FB-B1 C3 99 1D îφ·≤ßú²┤∩○τ√▒├Ö↔
30: CD 91 C8 45-E6 6E FD 3D-C7 BB 61 52-3E F4 E0 38 ═æ╚Eµn²=╟╗aR>⌠α8
40: 49 11 85 69-EB CC 17 9C-93 4F 40 EB-33 02 AD 20 I◄àiδ╠↨£ôO@δ3☻¡
50: A4 09 2D FB-15 FA 20 1D-D1 DB 17 CD-DD 29 59 1E ñ○-√§· ↔╤█↨═▌)Y▲ ................
60: 39 89 9E F6-79 46 9F E6-8B 85 C5 EF-DE 42 4F 46 9ë₧÷yFƒµïà┼∩▐BOF ...X............
70: C2 78 75 9D-8B 65 F4 50-EA 21 C5 59-18 62 FF 7B ┬xu¥ïe⌠PΩ!┼Y↑b { .............XX.
...........X....
................
00: 37 75 C1 F1-C4 A7 5A E7-9C E0 DE 7A-5B 10 80 26 7u┴±─ºZτ£α▐z[►Ç& ...X............
10: 02 AB D9 B9-C9 6C 5F 02-12 C2 7F DA-CD 0D A3 B0 ☻½┘╣╔l_☻↕┬⌂┌═♪ú░ .............XX.
20: 8C ED FA F3-E1 A3 FD B4-EF 09 E7 FB-B1 43 9A 1D îφ·≤ßú²┤∩○τ√▒CÜ↔ ...........X....
30: CD 91 C8 45-E6 6E FD 3D-C7 BB 61 D2-3E F4 E0 38 ═æ╚Eµn²=╟╗a╥>⌠α8
40: 49 11 85 69-EB CC 17 9C-93 4F 40 EB-33 02 AD 20 I◄àiδ╠↨£ôO@δ3☻¡ /
50: A4 09 2D 7B-15 FA 20 1D-D1 DB 17 CD-DD 29 59 1E ñ○-{§· ↔╤█↨═▌)Y▲
60: 39 89 9E F6-79 46 9F E6-8B 85 C5 EF-DE C2 4E 46 9ë₧÷yFƒµïà┼∩▐┬NF
70: C2 78 75 9D-8B 65 F4 50-EA 21 C5 D9-18 62 FF 7B ┬xu¥ïe⌠PΩ!┼┘↑b {
MD5: fe6c446ee3a831ee010f33ac9c1b602c SHA256: e27cf3073c704d0665da42d597d4d20131013204eecb6372a5bd60aeddd5d670
Other examples, with an identical prefix: [1](https://github.com/corkami/collisions/blob/HEAD/examples/fastcoll1.bin) ⟷ [2](https://github.com/corkami/collisions/blob/HEAD/examples/fastcoll2.bin)
**Variante**: esiste una [collisione MD5 a blocco singolo](https://marc-stevens.nl/research/md5-1block-collision/) ma richiede cinque settimane di calcolo.
Ecco una [registrazione](https://github.com/corkami/collisions/blob/HEAD/examples/fastcoll.svg) di un calcolo FastColl senza alcun prefisso
e [un'altra](https://github.com/corkami/collisions/blob/HEAD/examples/fastcoll-prefix.svg) con un prefisso.
### [UniColl](https://github.com/corkami/collisions/blob/HEAD/unicoll.md) (MD5)
Documentato nel [2012](https://www.cwi.nl/system/files/PhD-Thesis-Marc-Stevens-Attacks-on-Hash-Functions-and-Applications.pdf#page=199), implementato nel [2017](https://github.com/cr-marcstevens/hashclash/blob/95c2619a8078990056beb7aaa59104021714ee3c/scripts/poc_no.sh)
UniColl ti consente di controllare alcuni byte nei blocchi di collisione, prima e dopo la prima differenza, il che lo rende una collisione a prefisso identico con alcune differenze controllabili, quasi come una collisione a prefisso scelto.
Questo è molto comodo, e ancora meglio la differenza può essere molto prevedibile:
nel caso di `m2+= 2^8` (a.k.a. `N=1` / `m2 9` nello script HashClash [poc_no.sh](https://github.com/cr-marcstevens/hashclash/blob/master/scripts/poc_no.sh#L30)),
la differenza è +1 sul nono byte, il che la rende molto sfruttabile,
tanto che puoi persino pensare alla collisione a mente:
il nono carattere di quella frase verrà sostituito con il successivo: `0` sostituito da `1`, `a` sostituito da `b`..
- tempo: pochi minuti (dipende dalla quantità di byte che vuoi controllare )
- spazio: due blocchi
- differenze: ```
.. .. .. .. DD .. .. .. ..
.. .. .. .. +1 .. .. .. ..
Esempi con N=1 e 20 byte di testo impostato nei blocchi di collisione:```
00: 55 6E 69 43-6F 6C 6C 20-31 20 70 72-65 66 69 78 UniColl 1 prefix
10: 20 32 30 62-F5 48 34 B9-3B 1C 01 9F-C8 6B E6 44 20b⌡H4╣;∟☺ƒ╚kµD
20: FE F6 31 3A-63 DB 99 3E-77 4D C7 5A-6E B0 A6 88 ■÷1:c█Ö>wM╟Zn░ªê
30: 04 05 FB 39-33 21 64 BF-0D A4 FE E2-A6 9D 83 36 ♦♣√93!d┐♪ñ■Γª¥â6
40: 4B 14 D7 F2-47 53 84 BA-12 2D 4F BB-83 78 6C 70 K¶╫≥GSä║↕-O╗âxlp
50: C6 EB 21 F2-F6 59 9A 85-14 73 04 DD-57 5F 40 3C ╞δ!≥÷YÜà¶s♦▌W_@< .........X......
60: E1 3F B0 DB-E8 B4 AA B0-D5 56 22 AF-B9 04 26 FC ß?░█Φ┤¬░╒V"»╣♦&ⁿ ................
70: 9F D2 0C 00-86 C8 ED DE-85 7F 03 7B-05 28 D7 0F ƒ╥♀ å╚φ▐à⌂♥{♣(╫☼ ................
................
.........X......
00: 55 6E 69 43-6F 6C 6C 20-31 21 70 72-65 66 69 78 UniColl 1!prefix ................
10: 20 32 30 62-F5 48 34 B9-3B 1C 01 9F-C8 6B E6 44 20b⌡H4╣;∟☺ƒ╚kµD ................
20: FE F6 31 3A-63 DB 99 3E-77 4D C7 5A-6E B0 A6 88 ■÷1:c█Ö>wM╟Zn░ªê ................
30: 04 05 FB 39-33 21 64 BF-0D A4 FE E2-A6 9D 83 36 ♦♣√93!d┐♪ñ■Γª¥â6
40: 4B 14 D7 F2-47 53 84 BA-12 2C 4F BB-83 78 6C 70 K¶╫≥GSä║↕,O╗âxlp /
50: C6 EB 21 F2-F6 59 9A 85-14 73 04 DD-57 5F 40 3C ╞δ!≥÷YÜà¶s♦▌W_@<
60: E1 3F B0 DB-E8 B4 AA B0-D5 56 22 AF-B9 04 26 FC ß?░█Φ┤¬░╒V"»╣♦&ⁿ
70: 9F D2 0C 00-86 C8 ED DE-85 7F 03 7B-05 28 D7 0F ƒ╥♀ å╚φ▐à⌂♥{♣(╫☼
UniColl ha meno controllo di una vera collisione a prefisso scelto,
ma è molto più veloce, soprattutto perché richiede solo due blocchi.
Ecco una [registrazione](https://github.com/corkami/collisions/blob/HEAD/examples/unicoll.svg) di un calcolo UniColl.
### [Shattered](http://shattered.io) (SHA1)
Documentato nel [2013](https://marc-stevens.nl/research/papers/EC13-S.pdf), calcolato nel [2017](http://shattered.io).
- tempo: 6500 anni di CPU e 110 anni di GPU
- spazio: due blocchi
- differenze: ```
.. .. .. DD ?? ?? ?? ??
or
?? ?? ?? DD .. .. .. ..
La differenza tra i blocchi di collisione di ogni lato è questa maschera Xor:``` 0C 00 00 02 C0 00 00 10 B4 00 00 1C 3C 00 00 04 BC 00 00 1A 20 00 00 10 24 00 00 1C EC 00 00 14 0C 00 00 02 C0 00 00 10 B4 00 00 1C 2C 00 00 04 BC 00 00 18 B0 00 00 10 00 00 00 0C B8 00 00 10
Esempi: [PoC||GTFO 0x18](https://github.com/angea/pocorgtfo#0x18) utilizza i prefissi SHA1 calcolati,
riutilizzando l'immagine direttamente dal sorgente PDFLaTeX (vedi [articolo 18:10](https://archive.org/stream/pocorgtfo18#page/n62/mode/1up)),
ma verifica anche il valore dei prefissi tramite JavaScript nella pagina HTML (il file è poliglotta, ZIP HTML e PDF).
## Collisioni a prefisso scelto
Permettono di far collidere qualsiasi contenuto.
| 𝓐 | ≠ | 𝔅 |
| :----: |:-:| :----: |
| Collisione *A* | ≠ | Collisione *B* |
1. prendere due prefissi arbitrari
2. riempire il più corto finché sia lungo quanto il più lungo. entrambi vengono riempiti fino al blocco successivo - meno 12 byte
- questi 12 byte di dati casuali verranno aggiunti su entrambi i lati per randomizzare la ricerca del compleanno
3. verranno calcolati e aggiunti X blocchi di quasi-collisione.
Meno blocchi ci sono, più lungo è il calcolo.
Es: [400 kHours per un blocco](https://www.win.tue.nl/hashclash/SingleBlock/). 72 ore-core per nove blocchi con [HashClash](https://github.com/cr-marcstevens/hashclash).
Le collisioni a prefisso scelto sono potentissime, ma possono richiedere molto tempo anche solo per una coppia di file.
### [HashClash](https://github.com/cr-marcstevens/hashclash) (MD5)
Versione finale nel [2009](https://www.win.tue.nl/hashclash/ChosenPrefixCollisions/).
Esempi: facciamo collidere `yes` e `no`. Ci sono volute tre ore su 24 core.```
'yes' prefix:
000: 79 65 73 0A-3D 62 84 11-01 75 D3 4D-EB 80 93 DE yes◙=bä◄☺u╙MδÇô▐ - Prefix, padding
010: 31 C1 D9 30-45 FB BE 1E-71 F0 0A 63-75 A8 30 AA 1┴┘0E√╛▲q≡◙cu¿0¬
020: 98 17 CA E3-A2 6B 8E 3D-44 A9 8F F2-0E 67 96 48 ÿ↨╩πókÄ=D⌐Å≥♫gûH
030: 97 25 A6 FB-00 00 00 00-49 08 09 33-F0 62 C4 E8 ù%ª√ I◘○3≡b─Φ
040: D5 F1 54 CD-CA A1 42 90-7F 9D 3D 9A-67 C4 1B 0F ╒±T═╩íBÉ⌂¥=Üg─←☼ - Collision blocks start
050: 04 9F 19 E8-92 C3 AA 19-43 31 1A DB-DA 96 01 54 ♦ƒ↓ΦÆ├¬↓C1→█┌û☺T
060: 85 B5 9A 88-D8 A5 0E FB-CD 66 9A DA-4F 20 8A AA à╡Üê╪Ñ♫√═fÜ┌O è¬
070: BA E3 9C F0-78 31 8F D1-14 5F 3E B9-0F 9F 3E 19 ║π£≡x1Å╤¶_>╣☼ƒ>↓
080: 09 9C BB A9-45 89 BA A8-03 E6 C0 31-A0 54 D6 26 ○£╗⌐Eë║¿♥µ└1áT╓&
090: 3F 80 4C 06-0F C7 D9 19-09 D3 DA 14-FD CB 39 84 ?ÇL♠☼╟┘↓○╙┌¶²╦9ä
0A0: 1F 0D 77 5F-55 AA 7A 07-4C 24 8B 13-0A 54 A2 BC ▼♪w_U¬z•L$ï‼◙Tó╝
0B0: C5 12 7D 4F-E0 5E F2 23-C5 07 61 E4-80 91 B2 13 ┼↕}Oα^≥#┼•aΣÇæ▓‼
0C0: E7 79 07 2A-CF 1B 66 39-8C F0 8E 7E-75 25 22 1D τy•*╧←f9î≡Ä~u%"↔
0D0: A7 3B 49 4A-32 A4 3A 07-61 26 64 EA-6B 83 A2 8D º;IJ2ñ:•a&dΩkâóì
0E0: BE A3 FF BE-4E 71 AE 18-E2 D0 86 4F-20 00 30 26 ╛ú ╛Nq«↑Γ╨åO 0&
0F0: 0A 71 DE 1F-40 B4 F4 8F-9C 50 5C 78-DD CD 72 89 ◙q▐▼@┤⌠Å£P\x▌═rë
100: BA D1 BF F9-96 80 E3 06-96 F3 B9 7C-77 2D EB 25 ║╤┐∙ûÇπ♠û≤╣|w-δ%
110: 1E 56 70 D7-14 1F 55 4D-EC 11 58 59-92 45 E1 33 ▲Vp╫¶▼UM∞◄XYÆEß3
120: 3E 0E A1 6E-FF D9 90 AD-F6 A0 AD 0E-C6 D6 88 12 >♫ín ┘É¡÷á¡♫╞╓ê↕
130: B8 74 F2 9E-DD 53 F7 88-19 73 85 39-AA 9B E0 8D ╕t≥₧▌S≈ê↓sà9¬¢αì
\
140: 82 BF 9C 5E-58 42 1E 3B-94 CF 5B 54-73 5F A8 4A é┐£^XB▲;ö╧[Ts_¿J
150: FD 5B 64 CF-59 D1 96 74-14 B3 0C AF-11 1C F9 47 ²[d╧Y╤ût¶│♀»◄∟∙G ................
160: C5 7A 2C F7-D5 24 F5 EB-BE 54 3E 12-B0 24 67 3F ┼z,≈╒$⌡δ╛T>↕░$g? ................
170: 01 DD 95 76-8D 0D 58 FB-50 23 70 3A-BD ED BE AC ☺▌òvì♪X√P#p:╜φ╛¼ ...............X
................
180: B8 32 DB AE-E8 DC 3A 83-7A C8 D5 0F-08 90 1D 99 ╕2█«Φ▄:âz╚╒☼◘É↔Ö
190: 2D 7D 17 34-4E A8 21 98-61 1A 65 DA-FC 9B A4 BA -}↨4N¿!ÿa→e┌ⁿ¢ñ║ ................
1A0: E1 42 2B 86-0C 94 2A F6-D6 A4 81 B5-2B 0B E9 37 ßB+å♀ö*÷╓ñü╡+♂Θ7 ................
1B0: 44 D2 E4 23-14 7C 16 B8-84 90 8B E0-A1 A7 BD 27 D╥Σ#¶|▬╕äÉïαíº╜' ..............X.
................
1C0: C7 7E E6 17-1A 93 C5 EE-59 70 91 26-4E 9D C7 7C ╟~µ↨→ô┼εYpæ&N¥╟|
1D0: 1D 3D AB F1-B4 F4 F1 D9-86 48 75 77-6E FE 98 84 ↔=½±┤⌠±┘åHuwn■ÿä ................
1E0: EF 3C 1C C7-16 5A 1F 83-60 EC 5C FE-CA 17 0C 74 ∩<∟╟▬Z▼â`∞\■╩↨♀t ................
1F0: EB 8E 9D F6-90 A3 CD 08-65 D5 5A 4C-2E C6 BE 54 δÄ¥÷Éú═◘e╒ZL.╞╛T ...............X
................
'no' prefix: ................
000: 6E 6F 0A E5-5F D0 83 01-9B 4D 55 06-61 AB 88 11 no◙σ_╨â☺¢MU♠a½ê◄ ................
010: 8A FA 4D 34-B3 75 59 46-56 97 EF 6C-4A 07 90 CC è·M4│uYFVù∩lJ•É╠ ............X...
020: FE 19 D7 CF-6F 92 03 9C-91 AA A5 DA-56 92 C1 04 ■↓╫╧oÆ♥£æ¬Ñ┌VÆ┴♦ ................
030: E6 4C 08 A3-00 00 00 00-8D B6 4E 47-FF AF 7A 3C µL◘ú ì╢NG »z<
................
040: D5 F1 54 CD-CA A1 42 90-7F 9D 3D 9A-67 C4 1B 0F ╒±T═╩íBÉ⌂¥=Üg─←☼ ................
050: 04 9F 19 E8-92 C3 AA 19-43 31 1A DB-DA 96 01 54 ♦ƒ↓ΦÆ├¬↓C1→█┌û☺T ............X...
060: 85 B5 9A 88-D8 A5 0E FB-CD 66 9A DA-4F 20 8A A9 à╡Üê╪Ñ♫√═fÜ┌O è⌐ ................
070: BA E3 9C F0-78 31 8F D1-14 5F 3E B9-0F 9F 3E 19 ║π£≡x1Å╤¶_>╣☼ƒ>↓
................
080: 09 9C BB A9-45 89 BA A8-03 E6 C0 31-A0 54 D6 26 ○£╗⌐Eë║¿♥µ└1áT╓& ................
090: 3F 80 4C 06-0F C7 D9 19-09 D3 DA 14-FD CB 39 84 ?ÇL♠☼╟┘↓○╙┌¶²╦9ä .............X..
0A0: 1F 0D 77 5F-55 AA 7A 07-4C 24 8B 13-0A 54 B2 BC ▼♪w_U¬z•L$ï‼◙T▓╝ ................
0B0: C5 12 7D 4F-E0 5E F2 23-C5 07 61 E4-80 91 B2 13 ┼↕}Oα^≥#┼•aΣÇæ▓‼
................
0C0: E7 79 07 2A-CF 1B 66 39-8C F0 8E 7E-75 25 22 1D τy•*╧←f9î≡Ä~u%"↔ ................
0D0: A7 3B 49 4A-32 A4 3A 07-61 26 64 EA-6B 83 A2 8D º;IJ2ñ:•a&dΩkâóì ...............X
0E0: BE A3 FF BE-4E 71 AE 18-E2 D0 86 4F-20 00 30 22 ╛ú ╛Nq«↑Γ╨åO 0" ................
0F0: 0A 71 DE 1F-40 B4 F4 8F-9C 50 5C 78-DD CD 72 89 ◙q▐▼@┤⌠Å£P\x▌═rë
/
100: BA D1 BF F9-96 80 E3 06-96 F3 B9 7C-77 2D EB 25 ║╤┐∙ûÇπ♠û≤╣|w-δ%
110: 1E 56 70 D7-14 1F 55 4D-EC 11 58 59-92 45 E1 33 ▲Vp╫¶▼UM∞◄XYÆEß3
120: 3E 0E A1 6E-FF D9 90 AD-F6 A0 AD 0E-CA D6 88 12 >♫ín ┘É¡÷á¡♫╩╓ê↕
130: B8 74 F2 9E-DD 53 F7 88-19 73 85 39-AA 9B E0 8D ╕t≥₧▌S≈ê↓sà9¬¢αì
140: 82 BF 9C 5E-58 42 1E 3B-94 CF 5B 54-73 5F A8 4A é┐£^XB▲;ö╧[Ts_¿J
150: FD 5B 64 CF-59 D1 96 74-14 B3 0C AF-11 1C F9 47 ²[d╧Y╤ût¶│♀»◄∟∙G
160: C5 7A 2C F7-D5 24 F5 EB-BE 54 3E 12-70 24 67 3F ┼z,≈╒$⌡δ╛T>↕p$g?
170: 01 DD 95 76-8D 0D 58 FB-50 23 70 3A-BD ED BE AC ☺▌òvì♪X√P#p:╜φ╛¼
180: B8 32 DB AE-E8 DC 3A 83-7A C8 D5 0F-08 90 1D 99 ╕2█«Φ▄:âz╚╒☼◘É↔Ö
190: 2D 7D 17 34-4E A8 21 98-61 1A 65 DA-FC 9B A4 BA -}↨4N¿!ÿa→e┌ⁿ¢ñ║
1A0: E1 42 2B 86-0C 94 2A F6-D6 A4 81 B5-2B 2B E9 37 ßB+å♀ö*÷╓ñü╡++Θ7
1B0: 44 D2 E4 23-14 7C 16 B8-84 90 8B E0-A1 A7 BD 27 D╥Σ#¶|▬╕äÉïαíº╜'
1C0: C7 7E E6 17-1A 93 C5 EE-59 70 91 26-4E 9D C7 7C ╟~µ↨→ô┼εYpæ&N¥╟|
1D0: 1D 3D AB F1-B4 F4 F1 D9-86 48 75 77-6E FE 98 84 ↔=½±┤⌠±┘åHuwn■ÿä
1E0: EF 3C 1C C7-16 5A 1F 83-60 EC 5C FE-CA 17 0C 54 ∩<∟╟▬Z▼â`∞\■╩↨♀T
1F0: EB 8E 9D F6-90 A3 CD 08-65 D5 5A 4C-2E C6 BE 54 δÄ¥÷Éú═◘e╒ZL.╞╛T
Ecco un log dell'intera operazione.
Shambles è una chosen-prefix collision molto costosa che utilizza 9 blocchi.
Ogni blocco ha lo stesso pattern xor di Shattered:``` 0C 00 00 02 C0 00 00 10 B4 00 00 1C 3C 00 00 04 BC 00 00 1A 20 00 00 10 24 00 00 1C EC 00 00 14 0C 00 00 02 C0 00 00 10 B4 00 00 1C 2C 00 00 04 BC 00 00 18 B0 00 00 10 00 00 00 0C B8 00 00 10
But even if Shattered is much easier to exploit than FastColl,
the constraints of the differences in the collision blocks are irrelevant
since Shambles is a Chosen Prefix Collision.
## Riepilogo attacchi
Hash | Nome | Data | Durata | Tipo di prefisso | Controllo vicino alla differenza
---- | --------- | ---- | -------- | ----------- | -----------------
MD5 | FastColl | 2009 | 2s | Identico | nessuno
| UniColl | 2012 | 7-40min | Identico | 4-10 bytes
| HashClash | 2009 | 72h | Scelto | n/a
| | | | |
SHA1 | Shattered | 2013 | 6500yr | Identico | prefisso e suffisso
| Shambles | 2020 | ? | Scelto | n/a
# Sfruttamento
Le collisioni a prefisso identico sono generalmente considerate (molto) limitate, ma il prefisso scelto richiede tempo.
Un altro approccio è creare prefissi riutilizzabili tramite un attacco a prefisso identico come UniColl - o a prefisso scelto per superare alcune limitazioni - ma riutilizzare quella coppia di prefissi in combinazione con due payload come in un classico attacco a prefisso identico.
Una volta calcolata la coppia di prefissi, far collidere due contenuti diventa istantaneo:
basta solo manipolare i dati del file (secondo i formati specifici) affinché rispettino le specifiche dei formati e i requisiti del prefisso precalcolato.
## Strategia standard
Collisioni classiche di due file validi con lo stesso tipo di file.
### JPG
Limitazioni teoriche e soluzioni alternative:
- il segmento *Application* dovrebbe in teoria trovarsi subito dopo il marcatore *Start of Image*.
In pratica, questo non è necessario, quindi la nostra collisione può essere generica: l'unica limitazione è la dimensione dell'immagine più piccola.
- la lunghezza di un commento è memorizzata su due byte, quindi la quantità che può contenere è limitata a 65536 byte (all'incirca la dimensione di una foto 400x400)
- invece di saltare oltre un intero file JPG, si può dividere il file nei suoi segmenti e aggiungere trampolini di salto tra i segmenti
*commenti su ogni segmento dell'immagine*
*come funzionano i trampolini dei commenti*
- mentre la maggior parte della struttura di un JPG è composta da segmenti tutti limitati a 65536 byte di dimensione,
i dati compressi veri e propri sono memorizzati nel segmento *Entropy Coded Segment*, che non rispetta tali limitazioni:
la sua dimensione non è nota in anticipo e cresce oltre quel limite.
Cresce con la dimensione dell'immagine, costituendo gran parte della dimensione del file in un'immagine baseline (non progressiva).
Per far rientrare l'intera immagine in blocchi da 64kb, il modo semplice è provare prima a salvare l'immagine come progressiva (cosa che qualsiasi software può fare, e che divide l'ECS tipicamente in fino a sei scansioni). Il modo più avanzato è usare *JPEGTran* con il suo parametro da riga di comando 'wizard' `--scans` e definire scansioni personalizzate.
Non c'è alcun'altra restrizione oltre ai segmenti delle scansioni,
quindi una collisione MD5 di due JPG arbitrari è *istantanea* e non richiede una collisione a prefisso scelto, solo UniColl.
Con lo [script](https://github.com/corkami/collisions/blob/HEAD/scripts/jpg.py):```
21:07:35.65>jpg.py Ange.jpg Marc.jpg
21:07:35.75>
Esempi:
⟷
2 JPG in collisione MD5
Ecco un esempio di definizione delle scansioni JPEGTran per trasformare un'immagine RGB 1944x2508 in un JPG al 100% con 20 scansioni che rientrano tutte in 64 kb.``` // : -, , ;
// 0=luma 0: 0-0, 0, 0; 0: 1-1, 0, 0; 0: 2-6, 0, 0; 0: 7-10, 0, 0; 0: 11-13, 0, 0; 0: 14-20, 0, 0; 0: 21-26, 0, 0; 0: 27-32, 0, 0; 0: 33-40, 0, 0; 0: 41-48, 0, 0; 0: 49-54, 0, 0; 0: 55-63, 0, 0;
// 1=blueness 1: 0-0, 0, 0; 1: 1-16, 0, 0; 1: 17-32, 0, 0; 1: 33-63, 0, 0;
// 2=redness 2: 0-0, 0, 0; 2: 1-16, 0, 0; 2: 17-32, 0, 0; 2: 33-63, 0, 0;
Risultato:
*un''immagine RGB 1944x2508 come JPG al 100% con 20 scans*
### PNG
Limiti teorici e soluzioni alternative:
- Il PNG usa CRC32 alla fine dei suoi chunk, ma in pratica vengono ignorati. Possono essere corretti, ma non è richiesto.
- i metadati dell'immagine (dimensioni, spazio colore...) sono memorizzati nel chunk `IHDR`,
che in teoria dovrebbe trovarsi subito dopo la firma (cioè prima di qualsiasi commento),
quindi significherebbe che possiamo precalcolare collisioni solo di immagini con gli stessi metadati.
Tuttavia, quel chunk può in realtà trovarsi dopo un blocco di commento (nella stragrande maggioranza dei lettori, tranne quelli Apple), quindi possiamo mettere i dati della collisione prima dell'header,
il che consente di far collidere qualsiasi coppia di PNG con un singolo precalcolo.
Poiché un chunk PNG ha una lunghezza su quattro byte, non c'è bisogno di modificare la struttura di nessuno dei due file: possiamo saltare un'intera immagine in un colpo solo.
Possiamo inserire tutti i chunk scartati che vogliamo, quindi possiamo aggiungerne uno per l'allineamento, poi uno la cui lunghezza verrà alterata da una UniColl. così la lunghezza sarà `00` `75` e `01` `75`.
Quindi una collisione MD5 di due immagini PNG arbitrarie è *istantanea*, senza prerequisiti (nessun calcolo, solo alcune modifiche minori ai file), e non richiede una collisione a prefisso scelto, ma solo UniColl.
Con lo [script](https://github.com/corkami/collisions/blob/HEAD/scripts/png.py):```
19:27:04.79>png.py nintendo.png sega.png
19:27:04.87>
Esempi:
⟷
2 PNG in collisione MD5 con proprietà diverse
Ecco una registrazione dell'intera operazione.
La maggior parte dei lettori accetta senza problemi file PNG che iniziano con un chunk che non è IHDR.
Tuttavia, alcuni (come Safari e Anteprima - altri ancora?) non lo tollerano. In questo caso, l'header dell'immagine e le sue proprietà (dimensioni, spazio colore) devono venire per primi, prima di qualsiasi blocco di collisione.
In questo caso, entrambi i file in collisione devono avere le stesse proprietà. Ancora una volta, UniColl è sufficiente, e naturalmente la coppia di prefissi calcolata può essere riutilizzata per qualsiasi altra coppia di file con le stesse proprietà
Ecco uno script per far collidere qualsiasi coppia di questi file, che lancia UniColl se necessario per calcolare la coppia di prefissi.
Esempi:
⟷
⟷
2 coppie di PNG in collisione MD5 con proprietà identiche per la massima compatibilità
Ecco una registrazione dell'intera operazione quando viene invocato UniColl,
e un'altra quando il prefisso è già stato calcolato.
Il GIF è complicato:
Tuttavia, i chunk di commento seguono una struttura peculiare: è una catena di <length:1> <data:length> finché non viene definita una lunghezza nulla.
Quindi rende qualsiasi byte non nullo un valido 'salto in avanti'. Il che lo rende adatto all'uso con FastColl,
come mostrato in PoC||GTFO 14:11.
Quindi almeno, anche se non possiamo avere un prefisso generico, possiamo far collidere qualsiasi coppia di GIF con gli stessi metadati (dimensioni, palette) e ci serve solo un secondo di FastColl per calcolarne il prefisso.
Ora, il problema è che non possiamo saltare un'intera immagine come nel PNG o una grande struttura come nel JPG.
Una possibile soluzione alternativa è manipolare i dati compressi o suddividere l'immagine in piccole aree come nel caso della GIF hashquine, ma non è ottimale.
Un'altra idea che funziona in modo generico è che anche i dati dell'immagine vengono memorizzati usando questa struttura a sequenza length data:
quindi se prendiamo due GIF senza animazione, dobbiamo solo:
Con una configurazione minima (solo poche centinaia di byte di overhead), possiamo scivolare su qualsiasi immagine GIF e aggirare la limitazione dei 256 byte. Questa idea è stata suggerita da Marc, ed è brillante!
Quindi in conclusione, le attuali limitazioni del GIF per le collisioni MD5 istantanee sono:
gifsicle --use-colormap webUna scorciatoia semplice per normalizzare immagini GIF statiche è trasformarle in frame di animazione della stessa immagine, poi possiamo usare uno script per riutilizzare o calcolare blocchi FastColl e creare una coppia di file che mostri ciascuna di esse.
Esempi:
⟷
2 GIF in collisione MD5 - immagini di KidMoGraph
Ecco una registrazione dell'intera operazione.
Specifiche GZIP v4.3: RFC 1952 (1996).
1F 8B. Se non corrisponde alla firma, il parsing si fermerà, cosa che può essere usata per fermare forzatamente il parsing tra due payload, ma attiverà alcuni warning che potrebbero causare problemi. Un'altra strategia è aggiungere un membro vuoto extra alla fine del file e far terminare il parsing di entrambi i payload lì - sul membro o sul suo corpo.filename e il file comment opzionali sono terminati da null mentre l'Extra field è definito da size16, quindi abusabile. È composto da uno o più subfield, con un ID e la propria sotto-lunghezza, ma i subfield non vengono applicati - pochissimi sono definiti ufficialmente.Pertanto un membro gzip vuoto con un extra field è un perfetto host parassita.
Se il file superiore è troppo grande per stare in un extra field, il suo stream non compresso può essere suddiviso in file più piccoli finché non stanno tutti in extra field.
Dopo l'header di un membro vengono il suo corpo compresso, il suo CRC32 e la sua dimensione non compressa (non applicata). Pertanto un corpo dati vuoto con CRC32 e dimensione nulli costituisce un postwrap generico, che può persino essere condiviso da diversi header di membri.
Varie implementazioni si basano sulla dimensione non compressa dell'ultimo membro invece che sulla somma di tutti i membri. Quindi i nostri file in collisione risulteranno avere dimensione nulla, perché questi file terminano con un membro vuoto usato come trampolino.
Ecco uno script per generare collisioni MD5 istantanee di due file GZip. Impiega la maggior parte del tempo a decomprimere e ricomprimere i dati se i file di input sono grandi - i prefissi di collisione sono pre-calcolati. Suddividere i membri senza decomprimere non è possibile poiché il CRC32 non compresso deve essere calcolato.
Un .tar.gz è semplicemente l'archivio gzip di un archivio tar. Funzionerà bene con tar gzippati, a differenza di tar stesso.
Esempi: collision1.tar.gz (Pacome) ⟷ collision2.tar.gz (Reg)
LZ4 e Zstandard sono 2 diversi formati di compressione, con una struttura generale simile:
sono composti da frame, ciascuno dei quali inizia con un magic specifico: 0xFD2FB528 per i frame Zstandard, 0x184D2204 per i frame Lz4.
Condividono anche gli stessi frame TLV 'skippable', che iniziano con 4 byte magics nell'intervallo 0x184D2A50 - 0x184D2A5F, poi la Length dei dati utente (4 byte, little-endian), quindi i User Data stessi.
Questi frame sono del tutto facoltativi, di qualsiasi lunghezza e ripetibili. I file possono iniziare con questi frame. Quindi questi frame possono essere concatenati per creare un perfetto prefisso di collisione generico, attraverso 2 formati.
Ecco uno script per generare collisioni MD5 istantanee di due file Zstd/Lz4. Come per Gzip, 2 archivi diversi saranno visibili dall'esterno indipendentemente dal contenuto: per esempio, un .cpio.zst.
Esempi:
Il Portable Executable ha una struttura peculiare:
Quindi la strategia è:
DOS/Collisions/Header1/Header2. Devi solo applicare un delta agli offset delle due tabelle delle sezioni.Questo significa che è possibile far collidere istantaneamente qualsiasi coppia di eseguibili PE. Anche se usano sottosistemi o architetture diverse.
Mentre le collisioni di eseguibili sono solitamente banali tramite qualsiasi loader, questo tipo di sfruttamento qui è trasparente: il codice è identico e viene caricato allo stesso indirizzo.
Esempi: tweakPNG.exe (GUI) ⟷ fastcoll.exe (CLI)
Ecco uno script per generare collisioni MD5 istantanee di eseguibili Windows.
Il container di questo formato è una sequenza di chunk Length Type Value chiamati Atom.
La lunghezza è un big-endian a 32 bit e copre se stessa, il tipo e il valore, quindi la lunghezza normale minima è 8
(il tipo è una stringa di 4 caratteri ASCII).
Se la lunghezza è nulla, l'atom occupa il resto del file - come gli atom jp2c nei file JP2.
Se è 1, il Type è seguito da una lunghezza a 64 bit, trasformando l'atom in Type Length Value, rendendolo compatibile con altre collisioni come Shattered.
Alcuni atom contengono altri atom: in questi casi vengono chiamati box. Ecco perché questa struttura altrimenti senza nome è chiamata "atom/box".
Questo formato "atom/box" usato in MP4 è in realtà un derivato di Apple Quicktime, ed è usato da molti altri formati (JP2, HEIF, F4V).
Il primo tipo di atom è di solito ftyp, che consente di differenziare il formato di file effettivo.
Il formato è piuttosto permissivo:
basta concatenare atom free, abusare della lunghezza di uno con UniColl, poi saltare il primo payload.
Per i file MP4, l'unica cosa da aggiungere è adattare le tabelle stco (Sample Table - Chunk Offsets) o co64 (l'equivalente a 64 bit), poiché sono offset assoluti(!) che puntano ai dati video mdat - e vengono effettivamente applicati!
Questo dà origine a uno script che fa collidere istantaneamente qualsiasi video arbitrario - e come accennato, potrebbe funzionare su formati diversi dall'MP4.

Esempi (video di KidMoGraph):
lunghezze 32b (standard) collision1.mp4 ⟷ collision2.mp4
⟷
lunghezze 64b collisionl1.mp4 ⟷ collisionl2.mp4
⟷
Nota che alcuni visualizzatori (OS X, Safari, FireFox) non accettano un file che inizia con un Atom che non sia ftyp.
In questo caso, il prefisso deve coprire questo aspetto, e non è così generico, ma per il resto è la stessa strategia - solo limitata a un singolo tipo di file.
I file JPEG2000 di solito iniziano con la struttura Atom/Box come l'MP4,
poi l'ultimo atom jp2c in genere prosegue fino alla fine del file (lunghezza nulla),
quindi da questo punto in poi segue la struttura JFIF, come per il JPEG (che inizia con FF 4F come marcatore di segmento).
Anche la forma puramente JFIF è tollerata, nel qual caso la collisione è come per il JPEG: compatibile con Shattered, ma con commenti limitati a 64Kb.
D'altra parte, se manipoli file JPEG2000 con l'Atom/Box, non hai questa limitazione.
Come accennato prima, se stai cercando di far collidere questa struttura e
se ci sono ulteriori restrizioni - per esempio iniziare con un atom free non è tollerato da alcuni formati -
allora puoi calcolare un'altra coppia di prefissi UniColl specifica per questo formato:
JPEG2000 sembra imporre un atom 'jP ' prima del solito ftyp,
ma a parte questo, è l'unica restrizione: non c'è bisogno di riposizionare nulla.
Quindi lo script risultante è ancora più semplice!

Esempi: collision1.jp2 ⟷ collision2.jp2
A proposito di Shattered
Lo sfruttamento di Shattered non era un trucco del PDF, ma un trucco del JPG dentro un PDF.
Permetteva solo a un PDF di contenere un oggetto compresso in JPG che poteva avere due contenuti diversi. Entrambi i PDF dovevano essere per il resto totalmente identici.
Nota che i documenti possono essere del tutto normali e possono semplicemente ritagliare il JPG in collisione e visualizzarlo in punti diversi, come nei documenti multipagina.
Esempi: il documento Shattered, modificato ⟷ il documento Shattered, originale
il documento Shattered che usa un JPG in collisione in due punti
Collisioni PDF con MD5
Con MD5 (e altri schemi di collisione), possiamo realizzare collisioni PDF a livello di documento, senza alcuna restrizione su nessuno dei due file!
Il PDF ha una struttura molto diversa dagli altri formati di file. Usa numeri di oggetto e riferimenti per definire un albero. L'intero documento dipende dall'elemento Root.
Questo (valido) PDF``` text %PDF-1. 1 0 obj<</Pages 2 0 R>>endobj 2 0 obj<</Kids[3 0 R]/Count 1>>endobj 3 0 obj<</Parent 2 0 R>>endobj trailer <</Root 1 0 R>>
è equivalente a:``` text
%PDF-1.
11 0 obj<</Pages 12 0 R>>endobj
12 0 obj<</Kids[13 0 R]/Count 1>>endobj
13 0 obj<</Parent 12 0 R>>endobj
trailer <</Root 11 0 R>>
Trucchi:
XREF.Quindi memorizzare due alberi di documenti nello stesso file è accettabile. Dobbiamo solo fare in modo che l'oggetto radice faccia riferimento all'uno o all'altro oggetto radice di entrambi i documenti.
Quindi dobbiamo solo prendere due documenti,
rinumerare oggetti e riferimenti in modo che non ci siano sovrapposizioni,
creare una collisione in modo che il numero di elemento referenziato come oggetto Root possa essere cambiato mantenendo lo stesso valore hash,
il che è perfetto per UniColl con N=1, e adattare la tabella XREF di conseguenza.
In questo modo, possiamo far collidere in sicurezza qualsiasi coppia di PDF, indipendentemente da numeri di pagina, dimensioni, immagini...
commenti
Un PDF può memorizzare dati estranei in due modi:
\r e \n).
Questo può essere usato all'interno di un oggetto dizionario, per modificare ad esempio un riferimento a un oggetto, tramite UniColl.
Quindi questo è un oggetto PDF valido anche se contiene blocchi di collisione binari - basta riprovare finché non hai caratteri newline: ```
1 0 obj
<< /Type /Catalog /MD5_is /REALLY_dead_now__ /Pages 2 0 R
%¥┬•σe╕█╙X₧_~π▌╒εX∟■φe♦%τ8╞■[...]p╛╬ûFZ»‼v◘Åp↑╝%▓% ▼σφj╔◄dZ▀c²aU≤╨╩[├└─yNΓ5╔+▀╪yδ☻ß⌐░¼à(☺z₧
endobj
testo in collisione
Il primo caso permette di evidenziare la bellezza di UniColl, una collisione in cui le differenze sono prevedibili, così puoi scrivere poesie su dati in collisione - grazie Jurph!
Piuttosto che modificare la struttura del documento e ingannare i parser, useremo direttamente i blocchi di collisione per produrre testo, con lettura alternativa!``` V V Now he hash MD5, Now he hath MD5, No enemy cares! No enemy dares! Only he gave Only he have the shards. the shares. Can’t be owned & Can’t be pwned & his true gold, his true hold, like One Frail, like One Grail, sound as fold. sound as gold. ^ ^
Esempi: [poeMD5 A](https://github.com/corkami/collisions/blob/HEAD/examples/poeMD5_A.pdf) ⟷ [poeMD5 B](https://github.com/corkami/collisions/blob/HEAD/examples/poeMD5_B.pdf)
*Una vera creazione artistica crittografica :)*
(Nota: ho sbagliato con la compatibilità Adobe, ma è colpa mia, non di UniColl)
**struttura dei documenti in collisione**
Sia che tu usi UniColl come commento inline o chosen-prefix in un oggetto stream fittizio, la strategia è simile:
rimescola i numeri degli oggetti, poi fai puntare l'oggetto Root a oggetti diversi, quindi, a differenza di Shattered, questo significa collisione istantanea di qualsiasi coppia arbitraria di PDF, a livello di documento.
Un trucco utile è che l'output di [`mutool clean`](https://mupdf.com/docs/manual-mutool-clean.html) è prevedibilmente affidabile,
quindi può essere usato per normalizzare i PDF come input e correggere il PDF unito mantenendo le parti importanti del file non modificate.
MuTool non scarta chiavi/valori fasulli - a meno che non gli venga richiesto - e li mantiene nello stesso ordine,
quindi usare voci di dizionario finte come `/MD5_is /REALLY_dead_now__` è perfetto per allineare le cose in modo prevedibile senza bisogno di un altro tipo di commenti.
Tuttavia non mantiene i commenti nei dizionari (quindi niente trucco del commento inline)
Un modo semplice per eseguire l'operazione di rimescolamento degli oggetti senza problemi è semplicemente unire entrambi i file PDF
tramite `mutool merge` e poi dividere in due l'oggetto `/Pages`.
Per fare spazio a questo oggetto, basta unire un PDF fittizio davanti ai due documenti.
Facoltativamente, crea un riferimento fittizio all'array pendente
per impedire alla garbage collection di eliminare il secondo insieme di pagine.
**Esempio**:
con questo [script](https://github.com/corkami/collisions/blob/HEAD/scripts/pdf.py),
ci vogliono [meno di un secondo](https://github.com/corkami/collisions/blob/HEAD/examples/pdf.log) per far collidere i due paper PDF pubblici come Spectre e Meltdown:
Esempi: [spectre.pdf](https://github.com/corkami/collisions/blob/HEAD/examples/collision1.pdf) ⟷ [meltdown.pdf](https://github.com/corkami/collisions/blob/HEAD/examples/collision2.pdf)
Estensione possibile: concatenare i blocchi UniColl per conservare anche coppie dei vari [oggetti non critici](https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf#page=81)
che possono essere referenziati nell'oggetto Root - come `Outlines`, `Names`, `AcroForm` e Azioni Aggiuntive (`AA`) - nei file sorgente originali.
**in PDFLaTeX**
Le tecniche precedenti funzionano con una semplice coppia di file PDF,
ma è anche possibile farlo direttamente dai sorgenti TeX
tramite [specifici operatori PDFTeX](http://texdoc.net/texmf-dist/doc/pdftex/manual/pdftex-a.pdf).
Puoi definire oggetti direttamente - inclusi chiavi e valori fittizi per gli allineamenti - e definire oggetti vuoti per riservare alcuni slot di oggetti includendo questo all'inizio stesso dei tuoi sorgenti TeX:``` latex
% set PDF version low to prevent stream XREF
\pdfminorversion=3
\begingroup
% disable compression to keep alignments
\pdfcompresslevel=0\relax
\immediate
\pdfobj{<<
/Type /Catalog
% cool alignment padding
/MD5_is /REALLY_dead_now__
% the first reference number should be on offset 0x49,
% so the '2' object number will be changed to '3' by UniColl
/Pages 2 0 R
% now padding so that the collision blocks (ends at 0xC0) are covered
/0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
% with an extra character to be replaced by a return char
/0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0
>>}
% the original catalog of the shifted doc
\immediate\pdfobj{<</Type/Pages/Count 1/Kids[8 0 R]>>}
% the original catalog of the host doc
\immediate\pdfobj{<</Type/Pages/Count 1/Kids[33 0 R]>>}
% now we need to reserve PDF Objects so that there is no overlap
\newcount\objcount
% the host size (+3 for spare object slots) - 1
% putting a higher margin will just work, and XREF can have huge gaps
\objcount=25
\loop
\message{\the\objcount}
\advance \objcount -1
\immediate\pdfobj{<<>>} % just an empty object
\ifnum \objcount>0
\repeat
\endgroup
Non dimenticare di normalizzare l'output di PDFLaTeX - con mutool per esempio - se necessario:
Ottenere build riproducibili di PDFLaTeX tra distribuzioni è difficile - potresti anche voler agganciare il tempo di esecuzione per ottenere l'hash esatto se richiesto.
Ti aspetteresti che il JPG sia solo immagini, ma in un PDF e in alcuni lettori PDF (non browser, come Evince e Adobe Reader), può essere usato come contenuto di pagina proprio come qualsiasi altro oggetto incorporato, che è incorporato in un'immagine JPEG.
Per memorizzare i dati JPEG senza perdite, salvali come scala di grigi al 100%, quindi usa un'immagine di una singola riga/colonna, oppure ripeti la riga di dati 8 volte (dato che i blocchi JPEG sono 8x8), e i tuoi dati vengono memorizzati senza perdite e referenziati dalle pagine PDF.
Esempi di due PDF in collisione SHA-1 tramite dati di pagina JPEG (un'immagine in scala di grigi che renderizza colori) come contenuto di pagina vettoriale:
2 PDF in collisione SHA-1 con dati immagine memorizzati come JPG
È possibile referenziare il JPG in collisione due volte: come contenuto di pagina, senza perdite, che referenzia anche se stesso come immagine con perdita da visualizzare. Di nuovo, l'immagine da visualizzare è in scala di grigi, ma il contenuto di pagina può renderizzare alcuni colori tramite operatori PDF.
La parte superiore dell'immagine mostra il contenuto di pagina ripetuto 8 volte.
Esempi di due PDF in collisione SHA-1 tramite JPEG usato come dati di pagina e immagine da visualizzare:
Skulls & Crossbones ⟷ Golden Axe
2 PDF in collisione SHA-1 con JPG usato come immagine e contenuto di pagina
TL;DR Non esiste una collisione generica riutilizzabile per ZIP, ma esiste per i formati basati su ZIP. Dovrebbe essere possibile far collidere due file in 2h.core (36 volte più veloce del chosen-prefix)
Gli archivi ZIP sono un sandwich di 3 livelli (almeno).
Prima arriva il contenuto dei file (sequenza di strutture Local File Header, una per ogni file o directory archiviata),
poi un indice (di nuovo, una sequenza di Central Directory),
poi una singola struttura che punta a questo indice (End Of Central Directory).
L'ordine di questi livelli non può essere spostato. Alcuni parser necessitano solo della struttura del contenuto del file, ma non è un modo corretto di fare parsing e può essere abusato.
A causa di questo ordine richiesto, non esiste un prefisso generico che possa aiutare per qualsiasi collisione.
approccio non generico
Un altro approccio potrebbe essere semplicemente unire entrambi gli archivi, con i loro livelli uniti, e usare UniColl - ma con N=2, che introduce una differenza sul 4° byte - per eliminare la firma magica dell'End of Central Directory.
Questo significa che si potrebbe far collidere due ZIP arbitrari con un singolo UniColl e 24 byte di prefisso impostato.
Un tipico End of Central Directory, che è di 22 byte se il commento è vuoto:``` 00: 504b 0506 0000 0000 0000 0000 0000 0000 PK.............. 10: 0000 0000 0000 ......
Se usiamo questo come prefisso (portiamo il prefisso a 16 bit) per UniColl e `N=2`, la differenza è sul 4° byte, eliminando la magia `.P .K 05 06` modificandola prevedibilmente in `.P .K 05 86````
00: 504b 0506 0000 0000 0000 0000 0000 0000 PK..............
10: 0000 0000 0000 2121 eb66 cf9d db01 83bb ......!!.f......
20: 2888 4c41 e345 7d07 1634 5d4a 3b61 89a0 (.LA.E}..4]J;a..
30: 0029 94af 4168 2517 0bbc b841 cbf2 9587 .)..Ah%....A....
40: e438 0043 6390 279d 7c9e a01e e476 4c36 .8.Cc.'.|....vL6
50: 527f b1f4 653e d866 f98d 7278 5324 0bd5 R...e>.f..rxS$..
60: b31d ef6d d5d6 1163 5a2e a8a5 21bf eab4 ...m...cZ...!...
70: c59c 028e a913 f6b7 0036 c93f 5092 a628 .........6.?P..(
--no-pivot: salta il pivoting adversary-in-the-middle. Stabilisce solo un punto di accesso Wi-Fi rogue. (predefinito: false)--no-server: salta l'esecuzione del server web HTTPS necessario per eseguire attacchi adversary-in-the-middle. Utilizzare solo con altre opzioni come --no-pivot per alcuni scenari di test. (predefinito: false)--verbose: stampa un logging dettagliato su stdout, come l'output di dnsmasq. (predefinito: false)Alcuni esempi di invocazioni CLI con opzioni combinate:
.env, che ospiterai altrove: --no-server00: 504b 0586 0000 0000 0000 0000 0000 0000 PK.............. 10: 0000 0000 0000 2121 eb66 cf1d db01 83bb ......!!.f...... 20: 2888 4c41 e345 7d07 1634 5d4a 3b61 89a0 (.LA.E}..4]J;a.. 30: 0029 94af 4168 251f 0bbc b841 cbf2 9587 .)..Ah%....A.... 40: e438 00c3 6390 279d 7c9e a01e e476 4c36 .8..c.'.|....vL6 50: 527f b1f4 653e d866 f98d 72f8 5324 0bd5 R...e>.f..r.S$.. 60: b31d ef6d d5d6 1163 5a2e a8a5 21bf eab4 ...m...cZ...!... 70: c59c 028e a913 f6af 0036 c93f 5092 a628 .........6.?P..(
Questo non è affatto generico, ma molto più veloce della collisione con prefisso scelto:```
real 12m23.993s
user 112m24.072s
sys 2m0.194s
Un problema è che alcuni parser analizzano ancora i file ZIP al contrario anche se dovrebbero essere analizzati dal basso verso l'alto:
un modo per assicurarsi che entrambi i file vengano analizzati correttamente è concatenare due blocchi UniColl,
per abilitare/disabilitare ciascun End of Central Directory.
Per evitare che i parser ZIP si lamentino dello spazio inutilizzato,
si possono abusare degli Extra Fields,
dei commenti di file nella Central Directory e dei commenti di archivio nella End of Central Directory.

Esempio: ecco un sorgente assembly che descrive la struttura di uno ZIP duale, in grado di contenere due diversi file di archivio.
Dopo due computazioni UniColl, si ottengono i due file in collisione: collision1.zip ⟷ collision2.zip
Anche se il formato Zip stesso non può essere sfruttato genericamente come Gzip, alcuni formati che si basano su Zip possono essere sfruttati genericamente all'interno di archivi Zip con una struttura predefinita. È necessario prendere alcune precauzioni per rendere generica la collisione Zip.
Alcuni formati sono costituiti da più file memorizzati in un archivio Zip e si basano su un file radice con un nome file fisso che punta ad altri file nell'archivio. Molti di essi usano XML o testo per il file radice e memorizzano gli altri file così come sono.
Idea : far coesistere 2 set di file nello stesso archivio e puntare a uno o all'altro set di file. Un root generico può essere memorizzato all'inizio del file, ma i blocchi di collisione sono memorizzati fuori dal contenuto del file, nell'archivio (poiché le collisioni hanno un'entropia molto elevata, è impossibile sfruttare file XML o solo ASCII con collisioni).
Steps:
Mettere 2 set di file provenienti da 2 origini nello stesso archivio - cioè in diverse sottodirectory.
Modificare il file radice per puntare alternativamente a ciascun set.
Poiché timestamp, lunghezza e CRC del file radice sono memorizzati sia nel Local File Header - prima del contenuto del file - sia nella Central Directory - dopo il contenuto del file - questi valori non dovrebbero cambiare tra le due versioni dei file.
Central Directory, questa copia del valore potrebbe essere ignorata dal parser, ma forgiare un CRC32 su un valore costante è utile per evitare del tutto il problema.
Forgiare il CRC aggiungendo 4 byte casuali probabilmente non basta, poiché questi file radice sono tipicamente in XML o testo con sintassi rigide, e diventerebbero non validi.
CrcHack aiuta notevolmente a forgiare CRC con bit arbitrari e senza brute force, garantendo che il file di output sia ASCII e che i bit modificati siano ancora in un commento.Usare l'extra field di un file fittizio extra -- anche vuoto -- nell'archivio dopo il file radice è un modo elegante per memorizzare i blocchi di collisione Hashclash: in questo modo, l'archivio Zip mantiene una struttura standard e può essere facilmente manipolato in seguito, anche con strumenti standard.
Gli Extra Fields non hanno CRC32 e la loro lunghezza a 16 bit è dichiarata nelle intestazioni precedenti. Hanno un proprio formato interno ID:2 Size:2 Data, ma di solito viene ignorato, e sono presenti sia nel Local File Header sia nella Central Directory, ma possono essere assenti dalla Central Directory per mantenere il suffisso identico dopo i blocchi di collisione.
La presenza del file extra che copre i blocchi di collisione nel suo extra field potrebbe dover essere dichiarata nella struttura del formato, ad esempio nel file [Content_Types].xml in un documento OOXML. Altri file XML nel suffisso potrebbero dover essere modificati, poiché alcuni formati richiedono l'uso di percorsi assoluti.
Ecco la struttura complessiva dell'exploit generico per uno specifico formato basato su Zip:``` [Root file] (with constant CRC32)
[Dummy file] (with collision blocks in the extra field)
[...] <- rest of the archive, with 2 documents merged
Quindi, predefinendo i contenuti del file root e forgiando CRC32 ASCII, è possibile calcolare una collisione Hashclash generica e riutilizzabile per un formato specifico basato su zip.
### Riepilogo dei requisiti
- due o più prefissi
- uno o più tipi di file (i polyglot funzionano senza problemi)
- un file XML root con nome file, lunghezza e CRC fissi: queste informazioni sono presenti due volte, prima e dopo i blocchi di collisione
- i contenuti sono XML arbitrari
- è possibile aggiungere padding, anche tramite commento XML, per raggiungere la stessa lunghezza.
- il CRC può essere impostato (tramite CrcHack) su ogni contenuto.
- entrambi i gruppi di file coesistono nel suffisso, probabilmente in directory diverse. Alcuni strumenti hardcodano il percorso, il che può ridurre la compatibilità.
- potrebbe essere necessario unire un file XML *Content type* per coprire tutti i file, supportati e non supportati (blocchi di collisione e documento alternativo)
### Esempi
#### CRC32
Un commento XML minimale (solo ASCII) con un CRC32 contraffatto (calcolo immediato) con CrcHack.``` bash
echo "<!--ABCDEF-->" | crchack -b 4.0:+.8*6:1 -b 4.1:+.8*6:1 -b 4.2:+.8*6:1 -b 4.3:+.8*6:1 -b 4.4:+.8*6:1 -b 4.5:+.8*5:1 - 0xdeadf00d
<!--X{]EZF-->
Un altro esempio in cui si regola il CRC con il caso di un messaggio alfabetico.```bash echo "" | crchack.exe -b 4:+.8*32:.8 - 0xcafebabe
#### Collisioni
[zInsider](https://github.com/corkami/collisions/blob/HEAD/scripts/zinsider.py) è uno script per generare istantaneamente collisioni MD5 di coppie di documenti arbitrari usando questi formati ZIP+XML:
- Office Open XML: docx / pptx / xlsx
- Open Container Format: epub
- Open Packaging Conventions:
- formato di produzione 3D: 3mf
- XML Paper Specification: xps / oxps
Per generare i tuoi prefissi di collisione, [ecco uno script](https://github.com/corkami/collisions/blob/HEAD/scripts/makezip.py) per generare una coppia di zip radice.
Dopo aver calcolato le collisioni, usa [quest'altro script](https://github.com/corkami/collisions/blob/HEAD/scripts/extendzip.py) per combinare questa coppia di radici con un suffisso comune.
Alcuni PoC di collisione:
- Office Open XML: Excel ([1](https://github.com/corkami/collisions/blob/HEAD/examples/free/md5-1.xls) - [2](https://github.com/corkami/collisions/blob/HEAD/examples/free/md5-2.xls)), Powerpoint ([1](https://github.com/corkami/collisions/blob/HEAD/examples/free/md5-1.pptx) - [2](https://github.com/corkami/collisions/blob/HEAD/examples/free/md5-2.pptx)), Word ([1](https://github.com/corkami/collisions/blob/HEAD/examples/free/md5-1.docx) - [2](https://github.com/corkami/collisions/blob/HEAD/examples/free/md5-2.docx)).
- Open Container Format: Epub ([1](https://github.com/corkami/collisions/blob/HEAD/examples/collision-1.epub) - [2](https://github.com/corkami/collisions/blob/HEAD/examples/collision-2.epub)).
- Open Packaging Conventions: 3MF ([1](https://github.com/corkami/collisions/blob/HEAD/examples/collision-1.3mf) - [2](https://github.com/corkami/collisions/blob/HEAD/examples/collision-2.3mf)), XPS ([1](https://github.com/corkami/collisions/blob/HEAD/examples/collision-1.xps) - [2](https://github.com/corkami/collisions/blob/HEAD/examples/collision-2.xps)).
Alcuni formati con più file basati su Zip non possono essere sfruttati in modo generico:
- Quake PK3: uno zip di file senza una radice specifica.
- Open Document Format: il file `META-INF/manifest.xml` deve menzionare ogni altro file, quindi non può essere generico.
- APK, JAR, XPI: anche il file `META-INF/MANIFEST.mf` deve menzionare ogni altro file, con i suoi hash.
Grazie a [Philippe Lagadec](https://twitter.com/decalage2) per il suo aiuto sui formati di file Office!
### Altri
- Wasm, tramite una sezione personalizzata: [script](https://github.com/corkami/collisions/blob/HEAD/scripts/wasm.py), esempi: [md5-1.wasm](https://github.com/corkami/collisions/blob/HEAD/examples/free/md5-1.wasm) ⟷ [md5-2.wasm](https://github.com/corkami/collisions/blob/HEAD/examples/free/md5-2.wasm)
## Strategie poco comuni
Le collisioni riguardano di solito due file validi dello stesso tipo.
### MultiColls: catena di collisioni multiple
Niente impedisce di concatenare più blocchi di collisione e di avere più di due contenuti con lo stesso valore di hash.
Un esempio di ciò sono gli *hashquines* - che mostrano il proprio valore MD5.
Il file [PoCGTFO 14](https://github.com/angea/pocorgtfo#0x14) contiene 609 collisioni FastColl, per riuscirci attraverso due tipi di file nello stesso file.
#### Hashquines
Gli hashquines sono file che mostrano il proprio valore hash. Sono trattati [qui](https://github.com/corkami/collisions/blob/HEAD/hashquines/).
### Validità
Una strategia diversa sarebbe quella di eliminare il tipo di file per bypassare la scansione come file corrotto.
Basterà sovrascrivere la firma magica.
Accodare entrambi i file (validi o non validi) con un formato che non deve essere all'offset 0 (un archivio, come ZIP/RAR/...) rivelerebbe un altro tipo di file.
Questo consente collisioni poliglotte senza usare una collisione a prefisso scelto:
1. usa UniColl per abilitare o disabilitare una firma magica, ad esempio una PNG:
2. accoda un archivio ZIP
Anche se tecnicamente entrambi i file sono uno ZIP valido, poiché la maggior parte dei parser restituisce il primo tipo di file trovato e iniziano la scansione dall'offset 0, vedranno un tipo di file diverso.
Esempi:
⟷ [non valido](https://github.com/corkami/collisions/blob/HEAD/examples/png-invalid.png)
### PolyColls: collisioni di tipi di file diversi
È anche possibile avere entrambi i lati di una collisione con tipi diversi per ridurre i sospetti:
Scenario di attacco:
1. invia `holiday.jpg`
2. fallo inserire in whitelist
3. invia `evil.exe`, che ha lo stesso MD5.
In questi casi, è necessaria una collisione a prefisso scelto se entrambi i formati di file devono iniziare all'offset 0.
Alcuni esempi di layout polycoll:

*Polycoll PDF/JPG*

*Polycoll PE/PNG*
#### PE - JPG
Poiché un header PE è di solito più piccolo di 0x500 byte, è perfetto per un commento JPG:
1. inizia con gli header DOS/JPG
2. il commento JPEG salta oltre l'header PE
3. inserisci l'immagine JPG completa
4. inserisci tutte le specifiche PE
Ancora una volta, la collisione è [istantanea](https://github.com/corkami/collisions/blob/HEAD/scripts/jpgpe.py)
Esempi: [fastcoll.exe](https://github.com/corkami/collisions/blob/HEAD/examples/jpg-pe.exe) ⟷ [Marc.jpg](https://github.com/corkami/collisions/blob/HEAD/examples/jpg-pe.jpg)
#### PDF - PE
Unire un PDF con un file fittizio usando `mutool` è un buon modo generico per riordinare gli oggetti
e poi rendere i primi due oggetti scartabili (pagina fittizia e contenuto), che è la soluzione perfetta per ospitare un oggetto `stream` di lunghezza sconosciuta come `1 0`, e la sua lunghezza referenziata più avanti (dopo i blocchi di collisione) nel secondo oggetto.
L'unico problema è che `mutool` inserisce sempre la lunghezza in linea - e rimuove il riferimento alla lunghezza, quindi deve essere reinserita nel PDF al posto del valore, ma la maggior parte dei riferimenti `2 0 R` sarà più piccola delle lunghezze hardcoded.
Fortunatamente questo può essere sistemato senza alterare alcun offset di oggetto, quindi non è necessario patchare l'XREF.
Ecco uno [script](https://github.com/corkami/collisions/blob/HEAD/scripts/pdfpe.py) per, ad esempio, collidere istantaneamente un visualizzatore PDF ([Sumatra](https://www.sumatrapdfreader.org/free-pdf-reader.html) è leggero e autonomo) e un documento PDF:
Esempi: [Poster.pdf](https://github.com/corkami/collisions/blob/HEAD/examples/pepdf.pdf) ⟷ [Sumatra.exe](https://github.com/corkami/collisions/blob/HEAD/examples/pepdf.exe)

*un visualizzatore PDF che mostra un PDF (che a sua volta mostra un PDF) con lo stesso MD5*
#### PDF - PNG
Allo stesso modo, è possibile collidere ad esempio file PDF e PNG arbitrari senza restrizioni su nessuno dei due lati. È istantaneo, riutilizzabile e generico.
Esempi: [Hello.pdf](https://github.com/corkami/collisions/blob/HEAD/examples/png-pdf.pdf) ⟷ [1x1.png](https://github.com/corkami/collisions/blob/HEAD/examples/png-pdf.png)
### PileUps (multi-collision)
Le collisioni crittografiche non sono limitate a due file!
Come dimostrato nell'esperimento [Nostradamus](https://www.win.tue.nl/hashclash/Nostradamus/) del 2008, concatenare le collisioni rende possibile collidere più di due file.
Le prime collisioni possono essere identiche o a prefisso scelto, le successive devono essere a prefisso scelto.
Puoi chiamarle multi-collisioni, io preferisco *pileup* - è più corto :)
#### PE - PNG - MP4 - PDF
Combinando tutte le conoscenze acquisite in precedenza, ho usato 3 collisioni a prefisso scelto per creare 4 prefissi diversi per diversi tipi di file: documento (PDF), video (MP4), eseguibile (PE) e immagine (PNG).

*diagramma di un pileup PE/PNG/MP4/PDF*
Questo script è generico e istantaneo:

Esempi: [commodore.pdf](https://github.com/corkami/collisions/blob/HEAD/examples/pileup.pdf) ⟷ [diagram.png](https://github.com/corkami/collisions/blob/HEAD/examples/pileup.png) ⟷ [kidmo.mp4](https://github.com/corkami/collisions/blob/HEAD/examples/pileup.mp4) ⟷ [sumatra18.exe](https://github.com/corkami/collisions/blob/HEAD/examples/pileup.exe)
Poiché potresti distribuire un solo file ed è impossibile indovinare gli altri valori di prefisso da esso, una soluzione è incorporare tutti i prefissi della collisione in codice JavaScript e inserirli nei tuoi PoC, trasformando i tuoi file in [poliglotti HTML](https://github.com/corkami/collisions/blob/HEAD/examples/polyglot.html) per condividere facilmente i file in collisione correlati.
Il [numero 19](https://github.com/angea/pocorgtfo#0x19) di 'PoC or GTFO' è un tale pileup **e** poliglotta, che combina un documento di 80 pagine generato con PDFLaTeX, un visualizzatore PDF per Windows, un diagramma PNG e un breve video MP4 'collision' di [KidMoGraph](https://www.kidmograph.com/) con un payload HTML per generare gli altri file dalla release PDF (e anche un archivio ZIP):
Grazie a Rafał Hirsz per il suo aiuto costante su JavaScript.
## Casi d'uso
Meglio abbandonare del tutto l'MD5, perché l'introspezione dei file è semplicemente troppo dispendiosa in termini di tempo e troppo rischiosa!
### Devi colliderli tutti!
Un altro uso di collisioni istantanee, riutilizzabili e generiche sarebbe nascondere qualsiasi file di un determinato tipo - diciamo PNG - dietro file fittizi (o sempre lo stesso file) - cosa che in realtà si ottiene semplicemente concatenandolo allo stesso prefisso dopo aver rimosso la firma - si potrebbe persino fare a livello di libreria!
Da una rigorosa prospettiva di parsing, tutti i tuoi file mostreranno lo stesso contenuto, e le immagini maligne verrebbero rivelate come un file con lo stesso MD5 di quelli precedentemente raccolti.
Prendiamo due file:
⟷
e collidiamoli con la stessa PNG.
Ora mostrano la stessa immagine fittizia, e sono assolutamente identici fino alla 2ª immagine a livello di file!
⟷
Il loro payload maligno è nascosto dietro un file con lo stesso MD5 rispettivamente.
### File compromettenti
Un altro caso d'uso delle collisioni è nascondere qualcosa di compromettente dentro qualcosa di innocente, ma desiderabile: se l'unico modo per raccogliere prove è confrontare hash deboli, allora non puoi negare di non avere l'altro file (che mostra contenuti compromettenti ma nasconde contenuti innocenti).
I software in genere si concentrano sul parsing (rapido), non sull'analisi dettagliata dei file.
*un'immagine che mostra anteprime diverse in diverse schede di EnCase Forensic*
## Fallimenti
Non tutti i formati possono avere prefissi generici riutilizzabili: se una sorta di contenitore di dati non può essere inserito tra la firma magica e gli header standard che sono critici e specifici per ogni file, allora le collisioni generiche non sono possibili.
Naturalmente, si potrebbero comunque trasformare i vecchi file in un nuovo file, e persino usare codice per diramarsi su due payload diversi, ma è più una questione di porting dei payload che di collisione della struttura dei file.
### ELF
L'header ELF è richiesto all'offset 0 e contiene informazioni critiche come 32b/64b, endianness e ABI fin dall'inizio, quindi è impossibile avere un prefisso universale e poi blocchi di collisione prima dei parametri critici specifici del file originale.
### Mach-O
I file Mach-O non iniziano nemmeno con la stessa magia per 32b (`feedface`) e 64b (`feedfacf`). Subito dopo, c'è il numero e la dimensione dei comandi (come definizione dei segmenti, symtab, versione,...).
Come per ELF, le collisioni riutilizzabili non sono possibili.
### Java Class
Subito dopo la magia iniziale si trovano le versioni (che possono essere problematiche) ma anche il conteggio del constant pool, che è abbastanza specifico per ogni file, quindi niente collisioni universali per tutti i file.
Tuttavia, molti file hanno ancora una versione comune e possiamo riempire il constant pool più corto fino al conteggio più lungo.
Per prima cosa, inserisci una *literal UTF8* per allineare le informazioni, poi dichiarane un'altra con la sua lunghezza abusata da una UniColl (la lunghezza è memorizzata su 16 byte come big endian).
Tuttavia questo richiederà manipolazione del codice poiché tutti gli indici del pool saranno spostati.
Collisioni MD5 istantanee riutilizzabili per Java Class dovrebbero essere possibili, ma richiedono analisi e modifica del codice.
### TAR
**TL;DR** Nessuna collisione riutilizzabile per i file TAR, nessuna strategia oltre al prefisso scelto.
I Tape Archive sono una sequenza di header concatenati e contenuti di file, tutti allineati a 512 byte.
Non c'è una struttura centrale per l'intero file. Quindi nessun header globale o commento di alcun tipo da sfruttare.
Un trucco sarebbe iniziare un file fittizio di lunghezza variabile, ma la lunghezza è sempre allo stesso offset, il che non è compatibile con UniColl, il che significa che qui sono utili solo le collisioni a prefisso scelto.
## Riepilogo degli exploit
Format | Generic? | FastColl | UniColl | Shattered | HashClash / Shambles
-------- | -------- | :------: | :-----: | --------- | :-------:
PDF | S | | x | | x
JPG | S (1) | | x | x (2) | x
GZ | S | | x | | x
PNG | S/N (3) | | x | | x
MP4 | S (4) | | x | x (5) | x
PE | S | | | | x
ZIP-based (6) | S | | | | x
| | | | |
GIF | N | x | | | x
ZIP | N | | x (7) | | x
| | | | |
ELF | N | | | | x
TAR | N | | | | x
Mach-O | N | | | | x
Class | N | | | | x
1. JPG ha alcune limitazioni sui dati che possono essere migliorate in una certa misura manipolando la codifica delle scansioni.
2. PDF con JPG è l'[implementazione iniziale](http://shattered.io) dell'attacco Shattered, ma è solo un puro trucco JPG in un documento PDF.
3. PNG: Safari/Preview richiede che la PNG abbia il chunk `IHDR` nel primo slot, prima di qualsiasi blocco di collisione. Questo impedisce un prefisso generico, nel qual caso la collisione è limitata a dimensioni specifiche, spazio colore, BPP e interlacciamento.
4. I formati Atom/Box come MP4 possono funzionare con lo stesso prefisso per diversi sotto-formati. Alcuni sotto-formati come JPEG2000 o HEIF richiedono una preparazione extra, ma la strategia di exploit è la stessa - è solo che la collisione non è possibile tra sotto-formati, solo con una coppia di prefissi per uno specifico sotto-formato.
5. Atom/Box è compatibile con Shattered quando si usano lunghezze a 64 bit.
6. Alcuni formati basati su Zip possono essere sfruttati in modo generico.
7. Per una migliore compatibilità, ZIP richiede due UniColl per un archivio completo, e queste collisioni dipendono dai contenuti di entrambi i file.
## File di test
[Qui](https://github.com/corkami/collisions/blob/HEAD/examples/free/README.md) ci sono coppie di test in collisione libere (senza copyright, senza PII).
# Rilevamento
Ci sono diversi modi per rilevare le collisioni di hash nei file.
1. Due file: se hai due o più file con contenuti diversi e lo stesso hash, fai semplicemente un diff!
Tuttavia, se hai un solo file, può essere difficile capire se il file contiene una collisione di hash.
2. Struttura del file: analizza il file ai confini dei blocchi, e se noti blocchi ad alta entropia e magari prefisso/suffisso identici, potresti essere in grado di capire quale collisione sta usando, ma è molto soggetto a errori. Nel caso di una collisione a prefisso scelto, potrebbe essere impossibile individuarla, poiché entrambi i file potrebbero essere per lo più diversi oltre alla maggior parte dei blocchi di collisione.
3. Calcolo dell'hash: usa un'implementazione (in [C](https://github.com/cr-marcstevens/hashclash/tree/collisiondetection/src/collisiondetection) o [Go](https://github.com/therealmik/detectcoll)) del DetectColl di Marc Stevens (cfr. il suo articolo [Counter-cryptanalysis](https://marc-stevens.nl/research/papers/C13-S.pdf)). Richiede un solo file, ma richiede che la collisione sia in uno stato funzionante (il prefisso esatto e i suoi blocchi di collisione corrispondenti) ed è lento.
DetectColl fornisce informazioni tecniche sulla collisione stessa e mostra `*coll*` accanto all'hash collisionato.
## Esempio
Con il certificato del malware Flame:```
$ detectcoll flame.der
Found collision in block 11:
dm: dm4=80000000 dm11=ffff8000 dm14=80000000
ihv1=1ba33aac3a7f9ed70aec349b40390e85
ihv2=9ba33aac3c7f60ee8cebf69bc2391085
*coll* c38a66643af816f8438b375b5f42ccbb flame.der
ba2499ba3dda9ef818f854b75a2bd1cd9f2b7bed flame.der
Poiché Detectcoll può identificare i blocchi utilizzati per una collisione di hash, può mitigare la collisione tramite hash sicuri: se viene rilevato un blocco di collisione, lo rielabora nuovamente per rompere la proprietà di collisione. Quindi DetectColl è in grado di distinguere contenuti diversi tramite la stessa funzione di hash nonostante le collisioni nel file.
In breve:
Esempio con la collisione originale di Wang del 2005:``` $ md5sum wang* 79054025255fb1a26e4bc422aef54eb4 *wang1.bin 79054025255fb1a26e4bc422aef54eb4 *wang2.bin
MD5 sicuro su questi file:```
$ detectcoll wang1.bin | grep coll
*coll* ff531291d102a41aa131e0e09f64ca60 wang1.bin
I don't see any content to translate in the INPUT section. Please provide the actual chunk of Markdown content.``` $ detectcoll wang2.bin | grep coll coll 6a8e7124724d5c819401afc202a4fbd0 wang2.bin
## Firme
Per semplicità, puoi analizzare l'output di Detectcoll con questo [script](https://github.com/corkami/collisions/blob/HEAD/scripts/logparse.py) e farlo corrispondere più facilmente alle [firme note](https://github.com/corkami/collisions/blob/7f7876c431614f33f765bfc1cb62506b476a2eb0/scripts/logparse.py#L15-L24):``` shell
$ detectcoll_unsafe * | ./logparse.py
apop-1.bin
block: 2, collision: APop
cpc1.bin
block: 9, collision: HashClashCPC
fastcoll1.bin
block: 2, collision: FastColl
single-cpc1.bin
block: 1, collision: SingleCPC
single-ipc1.bin
block: 0, collision: SingleIPC
wang1.bin
block: 1, collision: FastColl
pileup.exe
block: 10, collision: HashClashCPC
block: 20, collision: HashClashCPC
04-unicoll-1.bin
block: 1, collision: Unicoll1
05-uc-n2-1.bin
block: 1, collision: Unicoll2
05-uc-n3-1.bin
block: 1, collision: Unicoll3
05-uc-n3-2.bin
block: 1, collision: Unicoll3
12-shattered1.bin
block: 3, collision: SHAttered/Shambles
block: 4, collision: SHAttered/Shambles
13-shambles1.bin
block: 9, collision: SHAttered/Shambles
13-shambles2.bin
block: 9, collision: SHAttered/Shambles
ca-rogue.der
block: 10, collision: HashClashCPC
flame.der
block: 11, collision: Flame
Un piccolo inconveniente degli hash sicuri è che impediscono il rilevamento di collisioni multiple nello stesso file, ma DetectColl può comunque rilevare collisioni con hash 'standard'.
Esempi con PoCorGTFO 0x14 (una NES+PDF hashquine con un'immagine di copertina alternativa).
Gli hash sicuri possono trovare solo una collisione:``` $ detectcoll_safe pocorgtfo14.pdf Found collision in block 135: dm: dm4=80000000 dm11=ffff8000 dm14=80000000 ihv1=73b615bd01d5e48032d3d1a549d0f956 ihv2=f3b615bd83d5e480b4d3d1a5cbd0f956 coll c4b085f9fa4b38669fa79d4c410538e9 pocorgtfo14.pdf eb5d0fb7607c1262236a5a7f591bb510ee9afbbc pocorgtfo14.pdf
Unsafe hashes li trova tutti:```
$ detectcoll_unsafe pocorgtfo14.pdf | grep Found | wc -l
609
Se controlli le ultime collisioni:``` $ detectcoll_unsafe pocorgtfo14.pdf | tail | grep Found Found collision in block 34169: Found collision in block 34250: Found collision in block 34324: Found collision in block 34389: Found collision in block 34456: Found collision in block 34523: Found collision in block 34585: Found collision in block 34738:
Puoi notare che l'ultima non è così vicina alle precedenti:
questo perché le precedenti appartengono allo stesso file immagine per gli hashquine,
mentre l'ultima è per la copertina alternativa.
# Riferimenti
Articoli (sullo sfruttamento dei formati di file):
- 2004
- [MD5 da considerarsi dannoso un giorno](https://eprint.iacr.org/2004/357.pdf) - Dan Kaminsky
- [Attacchi pratici alle firme digitali tramite MD5 Message Digest](https://eprint.iacr.org/2004/356.pdf) - Ondredj Mikle
- 2005:
- [Una nota sul valore pratico delle collisioni di hash singole per formati di file speciali](https://github.com/corkami/collisions/blob/HEAD/papers/Illies_NIST_05.pdf) - Max Gebhardt, Georg Illies, Werner Schindler
- 2014:
- [Hashing malevolo: la variante di Eve di SHA-1](https://malicioussha1.github.io/) - Ange Albertini, Jean-Philippe Aumasson, Maria Eichlseder, Florian Mendel, Martin Schläffer
- 2017:
- [La prima collisione per SHA-1 completo](http://shattered.io) - Marc Stevens, Elie Bursztein, Pierre Karpman, Ange Albertini, Yarik Markov
- [Postscript che mostra il proprio MD5](https://archive.org/stream/pocorgtfo14#page/n45/mode/1up) di Gregor "Greg" Kopf
- [Un PDF che mostra il proprio MD5](https://archive.org/stream/pocorgtfo14#page/n49/mode/1up) di Mako
- [Questa GIF mostra il proprio MD5!](https://archive.org/stream/pocorgtfo14#page/n52/mode/1up) di Kristoffer "spq" Janke
- [Questo PDF è una ROM NES che stampa il proprio hash MD5!](https://archive.org/stream/pocorgtfo14#page/n55/mode/1up) di Evan Sultanik, Evan Teran
- 2018:
- [PDF in collisione SHA-1 facili con PDFLaTeX.](https://archive.org/stream/pocorgtfo18#page/n62/mode/1up) di Ange Albertini
- 2020:
- [SHA-1 è un disastro](https://eprint.iacr.org/2020/014.pdf) di Gaëtan Leurent, Thomas Peyrin
Presentazioni:
- 2017 Sfruttare le collisioni di hash a Black Alps:
- [slide](https://speakerdeck.com/ange/exploiting-hash-collisions)
[](https://speakerdeck.com/ange/exploiting-hash-collisions)
- [video](https://www.youtube.com/watch?v=Y-oJWEYKVLA)
[](https://www.youtube.com/watch?v=Y-oJWEYKVLA)
- 2019 UCCIDI MD5 a Pass the Salt:
- [slide](https://speakerdeck.com/ange/kill-md5)
[](https://speakerdeck.com/ange/kill-md5)
- [video](https://passthesalt.ubicast.tv/videos/kill-md5-demystifying-hash-collisions/)
[](https://passthesalt.ubicast.tv/videos/kill-md5-demystifying-hash-collisions/)
Workshop (CollTris):
- [slide](https://speakerdeck.com/ange/colltris)
[](https://speakerdeck.com/ange/colltris)
- [video](https://www.youtube.com/watch?v=BcwrMnGVyBI)
[](https://www.youtube.com/watch?v=BcwrMnGVyBI)
- [materiali](https://github.com/corkami/collisions/blob/HEAD/workshop/README.md)
- sessioni
- 2019/07/02 150p, Pass The Salt
- 2019/07/24 199p, Google
- 2019/08/19 208p, Google
- 2019/10/23 222p, Hack.lu
- 2019/11/07 225p, Black Alps
- 2019/12/03 229p, Google
Sfide CTF:
- [Prudentialv2](https://ctftime.org/task/3453), dalla *Boston Key Party CTF 2017*.
- [HREFIN](https://ctftime.org/task/6965), dal *Google CTF 2018*.
- [Looking glass](https://ctftime.org/task/9271) dal *Dragon Sector Teaser CTF 2019*.
<!-- - [Not my digest](https://ctftime.org/task/4784) dal *Hack.lu CTF 2017*: non correlato alle collisioni, ma risolto da Marc stesso :p -->
Una difficoltà comune per tali sfide CTF è non dare un vantaggio o svantaggio troppo grande in base alla quantità di potenza di calcolo a cui ogni giocatore ha accesso.
# Crediti
Tutto questo è stato possibile grazie a [Marc Stevens](https://marc-stevens.nl/research/),
non solo per i suoi contributi crittografici, ma anche per il suo costante aiuto e i suoi suggerimenti!
Grazie anche a Philippe Teuwen per il suo ampio feedback sui formati di file in generale.
# Conclusione
**Uccidi MD5!**
A meno che non controlli attivamente la presenza di malformazioni o blocchi di collisione nei file, non usare MD5!
Non è un hash crittografico, è una funzione giocattolo!
<!-- pandoc -s -f gfm -t html README.md -o README.html -->
| Prefisso | = | Prefisso |
|---|
| Collisione A | ≠ | Collisione B |
| A | = | |
| = | B |