Headline
CVE-2021-44590: Memory allocation failure in cws2fws · Issue #236 · libming/libming
In libming 0.4.8, a memory exhaustion vulnerability exist in the function cws2fws in util/main.c. Remote attackers could launch denial of service attacks by submitting a crafted SWF file that exploits this vulnerability.
version: master(commit 04aee52 )
command: listswf $FILE
root:/path_to_libming/build/bin# ./listswf poc
==21798==WARNING: AddressSanitizer failed to allocate 0xffffffffb4b4b4b4 bytes
==21798==AddressSanitizer's allocator is terminating the process instead of returning 0
==21798==If you don't like this behavior set allocator_may_return_null=1
==21798==AddressSanitizer CHECK failed: /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:225 "((0)) != (0)" (0x0, 0x0)
#0 0x4e3385 in __asan::AsanCheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_rtl.cc:69
#1 0x500c45 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_termination.cc:79
#2 0x4e9786 in __sanitizer::ReportAllocatorCannotReturnNull() /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:225
#3 0x4e97c6 in __sanitizer::ReturnNullOrDieOnFailure::OnBadRequest() /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc:241
#4 0x41fadf in __asan::asan_realloc(void*, unsigned long, __sanitizer::BufferedStackTrace*) /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_allocator.cc:865
#5 0x4da689 in realloc /mnt/d/CLib/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:108
#6 0x53815f in cws2fws /path_to_libming/util/main.c:111:15
#7 0x53aacb in readMovieHeader /path_to_libming/util/main.c:198:18
#8 0x539dc3 in main /path_to_libming/util/main.c:350:5
#9 0x7f88a92b5bf6 in __libc_start_main /build/glibc-S9d2JN/glibc-2.27/csu/../csu/libc-start.c:310
#10 0x41a2f9 in _start (/path_to_libming/build/bin/listswf+0x41a2f9)
A large integer passed to realloc, causing the allocation failure.
The detailed call chain analysis is as follows.
Download poc
static int readMovieHeader(FILE *f, int *compressed) { char first; struct stat stat_buf;
first = readUInt8 (f);
\*compressed = (first == ('C')) ? 1 : 0;
if (!((first == 'C' || first == 'F') && readUInt8 (f) == 'W'
&& readUInt8 (f) == 'S'))
{
SWF\_error ("Doesn't look like a swf file to me..\\n");
}
m.version = readUInt8 (f);
m.size = readUInt32 (f); // Read 32 bits from the input file, the m.size is controllable by the attacker
m.soundStreamFmt = -1;
m.fonts = NULL;
m.numFonts = 0;
if (\*compressed)
{
#if USE_ZLIB int unzipped = cws2fws (f, m.size); … } … }
int cws2fws(FILE *f, uLong outsize) {
struct stat statbuffer;
int insize, ret;
int err,tmp\_fd;
Byte \*inbuffer,\*outbuffer;
sprintf(tmp\_name, "/tmp/swftoscriptXXXXXX");
#ifdef HAVE_MKSTEMP tmp_fd = mkstemp(tmp_name); #endif #ifndef HAVE_MKSTEMP tmp_fd = open(tmp_name, O_RDWR | O_CREAT | O_TRUNC , 0600); #endif
if ( tmp\_fd == -1 )
{
SWF\_error("Couldn't create tempfile.\\n");
}
tempfile = fdopen(tmp\_fd, "w+");
if ( ! tempfile )
{
SWF\_error("fdopen: %s", strerror(errno));
}
if( stat(filename, &statbuffer) == -1 )
{
SWF\_error("stat() failed on input file");
}
insize = statbuffer.st\_size\-8;
inbuffer = malloc(insize);
if(!inbuffer){ SWF\_error("malloc() failed"); }
if ( ! fread(inbuffer, insize, 1, f) )
{
SWF\_error("Error reading input file");
}
outbuffer=NULL;
do{
outbuffer = realloc(outbuffer, outsize); // outsize is controlled by the attacker, and it is directly passed to realloc without any boundary check, resulting in allocation failure
......
}while(err == Z\_BUF\_ERROR);
......
}