1 of 86

Schizophrenic�files

2014/06/02

Zürich, Switzerland

Ange Albertini

Gynvael Coldwind

Schizophrenic files

Area41

2 of 86

Gynvael Coldwind

Security researcher, Google

Dragon Sector captain

likes hamburgers

http://gynvael.coldwind.pl/

All opinions expressed during this presentation are mine and mine alone.

They are not opinions of my lawyer, barber and especially not my employer.

3 of 86

Ange Albertini

Reverse engineering

&

Visual Documentations

http://corkami.com

4 of 86

1 file + 2 tools�⇒ 2 different documents

No active detection in the file.

5 of 86

abusing parsers for

  • fun�
  • bypassing security
    • same-origin policy
    • evade detection
    • exfiltration
    • signing
      • Android Master Key

6 of 86

ZIP archives

7 of 86

excerpt from Gynvael's talk:

"Dziesięć tysięcy pułapek: ZIP, RAR, etc."

(http://gynvael.coldwind.pl/?id=523)

8 of 86

ZIP

trick 1

a glitch in the matrix

9 of 86

file names in ZIP

a couple of files with the same name?

update:

for an awesome example see:

Android: One Root to Own Them All

Jeff Forristal / Bluebox

(https://media.blackhat.com/us-13/US-13-Forristal-Android-One-Root-to-Own-Them-All-Slides.pdf)

10 of 86

ZIP

trick 2

abstract kitty

11 of 86

Let's start with simple stuff -�the ZIP format

A ZIP file begins with letters PK.

12 of 86

Let's start with simple stuff -�the ZIP format

A ZIP file begins with letters PK.

WRONG

13 of 86

ZIP - second attempt :)

.zip file

last 65557 bytes of the file�the "header" is "somewhere" here

PK\5\6...

14 of 86

ZIP - "somewhere" ?!

4.3.16 End of central directory record:

end of central dir signature 4 bytes (0x06054b50)

number of this disk 2 bytes

number of the disk with the

start of the central directory 2 bytes

total number of entries in the

central directory on this disk 2 bytes

total number of entries in

the central directory 2 bytes

size of the central directory 4 bytes

offset of start of central

directory with respect to

the starting disk number 4 bytes

.ZIP file comment length 2 bytes

.ZIP file comment (variable size)

you begin ZIP parsing

from this; it MUST be

at the end of the file

$0000-$FFFF

0-65535

22 bajty

Total: from 22 to 65557 bytes

(aka: PK\5\6 magic will be somewhere between EOF-65557 and EOF-22)

15 of 86

ZIP - looking for the "header"?

"From the START"

Begin at EOF-65557,

and move forward.

"From the END"

(ZIPs usually don't have comments)

Begin at EOF-22,

and move backward.

PK\5\6...

"somewhere"

PK\5\6...

"somewhere"

16 of 86

The show will continue in a moment.

Larch

Something completely different

17 of 86

ZIP Format - LFH

4.3.7 Local file header:�� local file header signature 4 bytes (0x04034b50)� version needed to extract 2 bytes� general purpose bit flag 2 bytes� compression method 2 bytes� last mod file time 2 bytes� last mod file date 2 bytes� crc-32 4 bytes� compressed size 4 bytes� uncompressed size 4 bytes� file name length 2 bytes� extra field length 2 bytes�� file name (variable size)� extra field (variable size)

file data (variable size)

random stuff

PK\3\4... LFH + data

Each file/directory in a ZIP has LFH + data.

18 of 86

ZIP Format - CDH

[central directory header n]�� central file header signature 4 bytes (0x02014b50)� version made by 2 bytes� version needed to extract 2 bytes general purpose bit flag 2 bytescompression method 2 bytes last mod file time 2 byteslast mod file date 2 bytescrc-32 4 bytescompressed size 4 bytesuncompressed size 4 bytes file name length 2 bytesextra field length 2 bytes file comment length 2 bytes� disk number start 2 bytes� internal file attributes 2 bytes� external file attributes 4 bytes� relative offset of local header 4 bytes�� file name (variable size)� extra field (variable size)� file comment (variable size)

similar stuff to LFH

PK\2\1... CDH

Each file/directory has a CDH entry in the Central Directory

thanks to the redundancy you can recover LFH using CDH, or CDH using LFH

19 of 86

ZIP - a complete file

PK\3\4... LFH + data

PK\5\6...EOCD

PK\2\1... CDH

Files (header+data)

List of files�(and pointers)

20 of 86

ZIP - a complete file (continued)

PK\3\4... LFH + data

PK\5\6...EOCD

PK\2\1... CDH

PK\3\4... LFH + data

PK\5\6...EOCD

PK\2\1... CDH

If the list of the files has pointers to files...

... the ZIP structure can be more relaxed.

21 of 86

ZIP - a complete file (continued)

PK\5\6...EOCD

PK\2\1... CDH

PK\3\4... LFH + data

file comment (variable size)

You can even do an "inception"

(some parsers may allow EOCD(CHD(LFH)))

22 of 86

And now back to our show!

(we were looking for the EOCD)

Larch

Something completely different

23 of 86

ZIP - looking for the "header"?

"stream"

Let's ignore EOCD!

(it's sometimes faster)

(99.9% of ZIPs out there can be parsed this way)

PK\3\4... LFH + data

PK\3\4... LFH + data

PK\3\4... LFH + data

(single "files" in an archive)

PK\5\6...

(who cares...)

24 of 86

ZIP - looking for the "header"?

"aggressive stream"

We ignore the "garbage"!

(forensics)

PK\3\4... LFH + data

PK\3\4... LFH + data

PK\3\4... LFH + data

(single "files" in an archive)

PK\5\6...

(who cares...)

25 of 86

Let's test the parsers!

abstract.zip

26 of 86

abstract.zip

EOCD

LFH+data

CDH

EOCD

LFH+data

CDH

LFH+data

LFH+data

syntax breaker

yellow is a comment of the green archive

stream

aggressive

stream

start-first

end-first

27 of 86

abstract.zip

from zipfile import ZipFile�ZipFile("abstract.zip", "r").printdir()

28 of 86

abstract.zip

<?php$za = new ZipArchive();$za->open('abstract.zip');for ($i=0; $i<$za->numFiles;$i++) {echo "index: $i\n";print_r($za->statIndex($i));}echo "numFile:" . $za->numFiles . "\n";

29 of 86

abstract.zip

import java.io.FileInputStream;import java.io.InputStream;import java.util.zip.ZipEntry;import java.util.zip.ZipInputStream;��public class zip {public static void main(String args[]) throws � java.io.IOException, java.io.FileNotFoundException {InputStream f = new FileInputStream("abstract.zip");ZipInputStream z = new ZipInputStream(f);�� ZipEntry e;while((e = z.getNextEntry()) != null) {System.out.println(e.getName());}}}

30 of 86

abstract.zip

31 of 86

abstract.zip

EOCD

CDH

EOCD

readme_StartFirst.txt

CDH

readme_AggressiveStream.txt

readme_Stream.txt

syntax breaker

readme_EndFirst.txt

Total Commander 8.01

UnZip 6.00 (Debian)

Midnight Commander

Windows 7 Explorer

ALZip

KGB Archiver

7-zip

b1.org

Python zipfile

JSZip

C# DotNetZip

perl Archive::Zip

Jeffrey's Exif Viewer

WOBZIP

GNOME File Roller

WinRAR

OSX UnZip

zip.vim v25

Emacs Zip-Archive mode

Ada Zip-Ada v45

Go archive/zip

Pharo smalltalk 2.0 ZipArchive

Ubuntu less

Java ZipFile

32 of 86

abstract.zip

EOCD

CDH

EOCD

readme_StartFirst.txt

CDH

readme_AggressiveStream.txt

readme_Stream.txt

syntax breaker

readme_EndFirst.txt

PHP ZipArchive

PHP zip_open ...

PHP zip:// wrapper

tcl + tclvfs + tclunzip

33 of 86

abstract.zip

EOCD

CDH

EOCD

readme_StartFirst.txt

CDH

readme_AggressiveStream.txt

readme_Stream.txt

syntax breaker

readme_EndFirst.txt

Ruby rubyzip2

Java ZipArchiveInputStream

java.util.zip.ZipInputStream

34 of 86

abstract.zip

EOCD

CDH

EOCD

readme_StartFirst.txt

CDH

readme_AggressiveStream.txt

readme_Stream.txt

syntax breaker

readme_EndFirst.txt

binwalk (found all)

35 of 86

abstract.zip - result summary

EOCD

CDH

EOCD

readme_StartFirst.txt

CDH

readme_AggressiveStream.txt

readme_Stream.txt

syntax breaker

readme_EndFirst.txt

Thanks!

  • Mulander
  • Felix Groebert
  • Salvation
  • j00ru

36 of 86

abstract.zip - who cares?

  • verify files via End-First�
  • unpack via Stream�

Oops.

37 of 86

abstract.zip - AV

EICAR test results (using VT):

  • most End-First
  • some Aggressive
  • Stream-only:
    • VBA32
    • NANO-Antivirus
    • Norman
    • F-Prot
    • Agnitum
    • Commtouch

https://docs.google.com/spreadsheet/ccc?key=0Apy5AGVPzpIOdDRPTFNJQXpqNkdjUzl4SE80c1kwdkE&usp=sharing

38 of 86

Portable Document File

39 of 86

40 of 86

41 of 86

42 of 86

% trailer <</Root …>>

trailer <</Root …>>

<</Root …>>

43 of 86

44 of 86

sometimes,�it’s in the specs

obscurity via over-specification?

45 of 86

notice anything unusual?

46 of 86

WYSIWYG

47 of 86

PDF Layers 1/2

“Optional Content Configuration”

  • principles
    • define layered content via various /Forms
    • enable/disable layers on viewing/printing
  • no warning when printing

  • “you can see the preview!”
    • bypass preview by keeping page 1 unchanged
    • just do a minor change in the file

48 of 86

PDF Layers 2/2

  • it’s Adobe only
    • what’s displayed varies with readers
    • could be hidden via previous schizophrenic trick
  • it was in the specs all along
    • very rarely used
    • can be abused

49 of 86

BMP

Trick 1

(originally published in Gynvael's "Format BMP okiem hakera" article in 2008)

50 of 86

FILE HEADER

INFO HEADER

PIXEL DATA

offset 0

offset N

bfOffBits

bfOffBits

Specifies the offset, in bytes, from the BITMAPFILEHEADER structure to the bitmap bits

(MSDN)

51 of 86

FILE HEADER

INFO HEADER

PIXEL DATA�(secondary)

offset 0

offset N

bfOffBits

bfOffBits

Specifies the offset, in bytes, from the BITMAPFILEHEADER structure to the bitmap bits

(MSDN)

PIXEL DATA

  • Some image viewers ignore bfOffBits and look for data immediately after the headers.

52 of 86

Different images, depending on which pixel data is used.

PIXEL DATA�(secondary)

PIXEL DATA

53 of 86

BMP

Trick 2�Something I've learnt about because it spoiled my steg100 task for a CTF (thankfully during testing).

54 of 86

BMP compression & palette

Run-Length Encoding (each box is 1 byte):

Length

>0

Palette Index (color)

Length

0

End of Line

0

Length

0

End of Bitmap

1

Length

0

Move Cursor

2

X offset

Y offset

Length

0

RAW Length

>2

Palette Index (color)

Palette Index (color)

...

55 of 86

BMP compression & palette

Question: If the opcodes below allow jump over pixels and set no data, how will the pixels look like?

Hint: Please take a look at the presentation title :)

Length

0

End of Line

0

Length

0

End of Bitmap

1

Length

0

Move Cursor

2

X offset

Y offset

56 of 86

Option 1

The missing data will be filled with background color.

(index 0 in the palette)

57 of 86

Option 2

The missing data will be black.

58 of 86

Option 3

The missing data will be transparent.�(pink represents transparency)

59 of 86

PNG

60 of 86

a data schizophren

image data combining

  • 2 images
  • via 2 palettes

cute PoC by @reversity

“There shall not be more than one PLTE chunk”

61 of 86

different images depending on which PLTE chunk is used

62 of 86

Portable Executable

63 of 86

Relocations types

W8

Vista

XP

Type 4

HIGH_ADJ

--

--

Type 9�MIPS_JMPADDR16

IA64_IMM64

MACHINE_SPEC_9

32 bit

64 bit

64 of 86

Relocations on relocations

Type 4

HIGH_ADJ

--

--

Type 9�MIPS_JMPADDR16

IA64_IMM64

MACHINE_SPEC_9

32 bit

64 bit

Type 10�DIR64

as seen in

PoC||GTFO

65 of 86

Relocation-based PE Schizophren

66 of 86

Julian Bangert, Sergey Bratus -- ELF Eccentricities

https://www.youtube.com/watch?v=4LU6N6THh2U

67 of 86

GIF

Something Gynvael stumbled on in 2008,�but never made a PoC... until now.

(with great input from Ange)

68 of 86

GIF

GIF can be made of many small images.

If "frame speed" is defined, these are frames instead�(and the first frame is treated as background).

x

x

x

y

y

y

69 of 86

GIF

Certain parsers (e.g. browsers) treat "images" as "frames" regardless of "frame speed" not being defined.

Frame 1

Frame 2

Frame 3

70 of 86

GIF

Certain parsers (e.g. browsers) treat "images" as "frames" regardless of "frame speed" not being defined.

Frame 1

Frame 2

Frame 3

71 of 86

GIF

Schizophrenic PoC:

Frame 1

Frames 2-10001

1x1 px

Frame 10002

72 of 86

These apps try to force animation.

These apps render the GIF by the specs.

73 of 86

GIMP says "frames", but allows one to see all the frames, which is nice.

74 of 86

same-tool schizophrenia

1 file + 1 tool = 2 behaviors

75 of 86

it was too simple

  • WinRar: different behavior when viewing or extracting
    • opening/failing
    • opening/’nothing’
  • Adobe: viewing ⇔printing
    • well, it’s a feature

76 of 86

Failures / Ideas / WIP

77 of 86

Screen ⇔ Printer schizophren

via color profiles?

78 of 86

Failures / Ideas / WIP

  • screen ⇔ printer
    • embedded color profiles?
  • JPG
    • IrfanView vs the world
  • Video
    • FLV: video fails but still plays sound ?

79 of 86

PNG

Various ancillary chunks (rendering level)

  • partially supported:
    • gamma
    • transparency (for palettes)
  • never supported?
    • significant bits
    • chromacities
  • always supported?
    • physical size

80 of 86

Conclusion

81 of 86

Conclusion

  • such a mess
    • specs are messy
    • parsers don’t even respect them�
  • no CVE/blaming for parsing errors?
    • no security bug if no crash or exploit :(

PoCs and slides: http://goo.gl/Sfjfo4

82 of 86

ACK

@reversity @travisgoodspeed @sergeybratus

qkumba @internot @pdfkungfoo�

@j00ru ise ds vx

83 of 86

thank you

questions?

Ange Albertini

Gynvael Coldwind

It's time to kick ass and chew bubble gum... and I'm all outta gum.

84 of 86

Flash (SWF) vs Prezi

vs

Bonus Round

(not a fully schizophrenic problem in popular parsers, that's why it's here)

85 of 86

Prezi SWF sanitizer

Prezi allows embedding SWF files.

But it first sanitizes them.

It uses one of two built-in SWF parsers.

There was a problem in one of them:

  • It allowed huge chunk sizes.
  • It just "jumped" (seeked) over these chunk...
  • ...which resulted in an integer overflow...
  • ...and this lead to schizophrenia.
  • As the sanitizer saw a good SWF...
  • ...Adobe Flash got its evil twin brother.

86 of 86

Prezi SWF sanitizer

"good" SWF sent to sanitizer

and its evil twin brother

kudos to the sanitizer!

Fixed in Q1 2014. For details see:

"Integer overflow into XSS and other fun stuff - a case study of a bug bounty"

http://gynvael.coldwind.pl/?id=533