- Package:
- cabextract
- Source:
- cabextract
- Description:
- Microsoft Cabinet file unpacker
- Submitter:
- Jakub Wilk
- Date:
- 2021-04-07 12:15:09 UTC
- Severity:
- minor
The attached file makes cabextract hang forever (or at least for two minutes, after which I lost my patience :-P). This bug was found using American fuzzy lop: http://lcamtuf.coredump.cx/afl/
and never gets out of the loop on line 290.
The problem seems to be on this line:
/* decode more, up to the number of bytes needed, the frame boundary,
* or the window boundary, whichever comes first */
frame_end = window_posn + (out_bytes - (qtm->o_end - qtm->o_ptr));
out_bytes is an off_t (8 bytes) but frame_end is an unsigned int (4
bytes) and it overflows.
If I change the "unsigned int" to "off_t" in the first line of this
function, the function terminates properly and declares the file
corrupt:
marvin% ./cabextract ~/Download/hang.cab
Extracting cabinet: /home/sharkey/Download/hang.cab
extracting limerick
limerick: error in CAB data format
All done, errors in processing 1 file(s)
Stuart, is this the right fix in your opinion?
Eric
Control: clone -1 -2
Control: reassign -2 libmspack0 0.4-1
Control: retitle -2 libmspack: hangs on a crafted CAB file
This issue also affects libmspack. I noticed this while clamav was
scanning Jakub's mail for malware and it was stuck in an infinite loop.
The issue is easy to reproduce with the crafted file and the following
example code:
#include <stdio.h>
#include <unistd.h>
#include <mspack.h>
int main()
{
struct mscab_decompressor *cabd;
struct mscabd_cabinet *cab;
struct mscabd_file *file;
int test;
MSPACK_SYS_SELFTEST(test);
if (test != MSPACK_ERR_OK) exit(0);
if ((cabd = mspack_create_cab_decompressor(NULL))) {
if ((cab = cabd->open(cabd, "hang.cab"))) {
for (file = cab->files; file; file = file->next) {
printf("%s\n", file->filename);
cabd->extract(cabd, file, file->filename);
}
cabd->close(cabd, cab);
}
mspack_destroy_cab_decompressor(cabd);
}
return 0;
}
(From https://github.com/cooljeanius/libmspack/blob/master/README with a
call to extract added.)
Cheers
I'm planning not to fix this bug directly. I'll be uploading a new build in a few days which fixes bug #675560, after which I'll close this as a duplicate of bug #773041. Eric
I added a patch based on your suggestions to #773041. If you close this bug as a duplicate then you won't see that this bug still affects Wheezy, correct? If you close both bugs (this + use libclamav) with your new upload then one would still see that Wheezy is affected. Sebastian
* Sebastian Ramacher <sramacher@debian.org>, 2014-12-13, 15:44: Ooops. Apologies to the clamav users for the disruption.
4294967231 and 'offset' of 255, which when added together requests exactly
2^32 bytes of data to be unpacked. When computed using or cast to a 32-bit
int / unsigned int, this is zero. Getting past "more than zero" tests by
being a 64-bit off_t leads to the infinite loop when cast down to a 32-bit
unsigned int.
The CAB file format itself doesn't support folder offsets/file lengths >2^31
(*). I think it makes sense to do better input validation and reject invalid
sizes, than try to write decompression code that processes invalid sizes.
While changing variables to off_t fixes a bug that appears with 64-bit
off_t, I'm not sure it doesn't introduce bugs on systems with 32-bit off_t.
Two unsigned ints <2^31 added together fit in an unsigned int but not a
32-bit off_t.
Below the change I intend to apply for this. I'll release new versions of
libmspack and cabextract in the near future, once I've fixed the other bugs
that have recently been found.
Regards
Stuart
Index: mspack/cabd.c
===================================================================
--- mspack/cabd.c (revision 198)
+++ mspack/cabd.c (working copy)
@@ -445,6 +445,19 @@
file->attribs = EndGetI16(&buf[cffile_Attribs]);
file->offset = EndGetI32(&buf[cffile_FolderOffset]);
+ /* check that neither offset, length nor offset+length exceed the max
+ * length of a folder. offset and length are tested first. If they're both
+ * less than CAB_LENGTHMAX, which is less than 2^31, then their sum must
+ * be less than 2^32, so they do not overflow an unsigned int comparison.
+ */
+ if (file->offset > CAB_LENGTHMAX ||
+ file->length > CAB_LENGTHMAX ||
+ (file->offset + file->length) > CAB_LENGTHMAX)
+ {
+ D(("invalid offset, length or offset+length"))
+ return MSPACK_ERR_DATAFORMAT;
+ }
+
/* set folder pointer */
x = EndGetI16(&buf[cffile_FolderIndex]);
if (x < cffileCONTINUED_FROM_PREV) {
@@ -937,6 +950,12 @@
return 0;
}
+ /* check there are not too many data blocks after merging */
+ if ((lfol->base.num_blocks + rfol->base.num_blocks) > CAB_FOLDERMAX) {
+ D(("folder merge: too many data blocks in merged folders"))
+ return 0;
+ }
+
if (!(lfi = lfol->merge_next) || !(rfi = rfol->merge_prev)) {
D(("folder merge: one cabinet has no files to merge"))
return 0;
Index: mspack/cab.h
===================================================================
--- mspack/cab.h (revision 198)
+++ mspack/cab.h (working copy)
@@ -70,6 +70,13 @@
#define CAB_BLOCKMAX (32768)
#define CAB_INPUTMAX (CAB_BLOCKMAX+6144)
+/* There are no more than 65535 data blocks per folder, so a folder cannot
+ * be more than 32768*65535 bytes in length. As files cannot span more than
+ * one folder, this is also their max offset, length and offset+length limit.
+ */
+#define CAB_FOLDERMAX (65535)
+#define CAB_LENGTHMAX (CAB_BLOCKMAX * CAB_FOLDERMAX)
+
/* CAB compression definitions */
(*): The maximum size of any cab folder is 65535 datablocks, unless you take
the generous interpretation that two folders are allowed to merge to become
a >65535 datablock folder. I haven't seen any such cab files in the wild,
but I have seen MS employees bemoan their file format's lack of support for
>2GB files, so I'm taking it as read that 65535 blocks is the upper limit
for one folder. Blocks are <=32768 bytes each when unpacked, so the maximum
unpacked folder size is 65535*32768 = 2147450880 bytes. Files (in the cab
file) can't span more than one folder, so the maximum offset+length of any
file is also 2147450880 bytes.
Hi Dear, how are you today I hope that everything is OK with you as it is my great pleasure to contact you in having communication with you starting from today, i was just going through the Internet search when i found your email address, I want to make a very new and special friend, so i decided to contact you to see how we can make it work if we can. Please i wish you will have the desire with me so that we can get to know each other better and see what happens in future. My name is Lisa Williams, I am an American presently I live in the UK, I will be very happy if you can write me through my private email address( willianslisa741@yahoo.com ) for easy communication so that we can know each other, I will give you my pictures and details about me. bye Lisa
لقد تم منحك مبلغ 1،300،000 دولار أمريكي من مؤسسة عبد الله الغرير دبي ، الإمارات العربية المتحدة لبرنامج المعونة الإنسانية / تخفيف وطأة الفقر. الرد على البريد الإلكتروني لدينا: email@online-grant.org<mailto:email@online-grant.org> اكتب اسمك عنوان رقم ولاية الرد على البريد الإلكتروني لدينا: email@online-grant.org<mailto:email@online-grant.org> Subject: RE: Doodle Mobile Envoyé depuis mon mobile Huawei Régine Degioanni Enseignante en Education Socio-culturelle LEPRP Jeanne Antide 55 impasse du Brévent 74 930 Reignier 04 50 43 87 65 06 47 56 92 10
Hello, We arespecialized in QA/software testing and we work particularly with organizationslike yours to resolve any development challenges. Theconversations we’re having with clients revolve around: - Manual andautomated testing - Regressiontesting -Performance testing - API and DBtesting Given ourexpertise working with technology products and our research, I thought thiswould be relevant. Our clientsare some of the most trusted brands across major industries, includinggoldi.com(HR video platform), Fetch my order(POS software), or optixapp.com(two-sidedB2B marketplace). We’d love todiscuss whether there is any room for cooperation. If this sounds even remotelyinteresting, can we connect at some stage this week for a brief 15-min call? Regards, James Williams