Bugzilla – Bug 11939
UAF in textIterate (mbox.c)
Last modified: 2021-09-23 16:36:49 EDT
Created attachment 7304 [details] poc, pass is virus There is an Use-After-Free dealing with Bounce messages. The UAF happens at `text.c:446` inside the function `textIterate`: ```c 444 if(destroy) 445 while(t_text) { 446 (*cb)(t_text->t_line, arg); 447 ``` Backtrace: ```c #0 0x62ab94 in textIterate /home/default/clamav-devel/libclamav/text.c:446:18 #1 0x62b07e in textToFileblob /home/default/clamav-devel/libclamav/text.c:380:7 #2 0x605bed in parseEmailBody /home/default/clamav-devel/libclamav/mbox.c:2381:32 #3 0x5fd13e in cli_parse_mbox /home/default/clamav-devel/libclamav/mbox.c:555:11 #4 0x5fc091 in cli_mbox /home/default/clamav-devel/libclamav/mbox.c:353:9 #5 0x5dd62c in cli_scanmail /home/default/clamav-devel/libclamav/scanners.c:2010:16 #6 0x5c4d31 in magic_scandesc /home/default/clamav-devel/libclamav/scanners.c:3294:19 #7 0x5cb434 in cli_map_scandesc /home/default/clamav-devel/libclamav/scanners.c:3779:15 #8 0x5cc771 in scan_common /home/default/clamav-devel/libclamav/scanners.c:3896:16 #9 0x5ccbf7 in cl_scanmap_callback /home/default/clamav-devel/libclamav/scanners.c:4042:12 ``` Another backtrace, without using the cl_scanmap function: ```c #0 0x81b8b9e in textIterate /tmp/clamav-devel/libclamav/text.c:446:4 #1 0x81b8b9e in textToFileblob /tmp/clamav-devel/libclamav/text.c:380 #2 0x81988b9 in parseEmailBody /tmp/clamav-devel/libclamav/mbox.c:2385:32 #3 0x8194e47 in cli_parse_mbox /tmp/clamav-devel/libclamav/mbox.c:555:11 #4 0x8194e47 in cli_mbox /tmp/clamav-devel/libclamav/mbox.c:353 #5 0x8182f73 in cli_scanmail /tmp/clamav-devel/libclamav/scanners.c:2010:16 #6 0x816e5d2 in magic_scandesc /tmp/clamav-devel/libclamav/scanners.c:3291:19 #7 0x8167904 in cli_base_scandesc /tmp/clamav-devel/libclamav/scanners.c:3616:11 #8 0x8176391 in cli_magic_scandesc /tmp/clamav-devel/libclamav/scanners.c:3625:12 #9 0x8176391 in scan_common /tmp/clamav-devel/libclamav/scanners.c:3891 #10 0x8177162 in cl_scandesc_callback /tmp/clamav-devel/libclamav/scanners.c:4032:12 #11 0x8177162 in cl_scanfile_callback /tmp/clamav-devel/libclamav/scanners.c:4099 #12 0x8177162 in cl_scanfile /tmp/clamav-devel/libclamav/scanners.c:4082 ``` The variable `t_text` is freed previously at `messageToFileblob`->`textDestroy`. Here is the call stack during the freeing: ```c freed by thread T0 here: #0 0x4e1a52 in free (/home/default/clamav-devel/clamavfuzz_libFuzzer+0x4e1a52) #1 0x629a39 in textDestroy /home/default/clamav-devel/libclamav/text.c:129:3 #2 0x623493 in messageToFileblob /home/default/clamav-devel/libclamav/message.c:1490:3 #3 0x604590 in parseEmailBody /home/default/clamav-devel/libclamav/mbox.c:2163:10 #4 0x5fd13e in cli_parse_mbox /home/default/clamav-devel/libclamav/mbox.c:555:11 #5 0x5fc091 in cli_mbox /home/default/clamav-devel/libclamav/mbox.c:353:9 #6 0x5dd62c in cli_scanmail /home/default/clamav-devel/libclamav/scanners.c:2010:16 #7 0x5c4d31 in magic_scandesc /home/default/clamav-devel/libclamav/scanners.c:3294:19 #8 0x5cb434 in cli_map_scandesc /home/default/clamav-devel/libclamav/scanners.c:3779:15 #9 0x5cc771 in scan_common /home/default/clamav-devel/libclamav/scanners.c:3896:16 #10 0x5ccbf7 in cl_scanmap_callback /home/default/clamav-devel/libclamav/scanners.c:4042:12 ``` The text trying to be display belongs to the body of the email, this text is freed after the message has been converted to `fileblob`. But after this step ClamAV tries to look for viruses hidden inside the HTML: ```c 2340 /* 2341 * No attachments - scan the text portions, often files 2342 * are hidden in HTML code 2343 */ ... 2364 else if((t_line = encodingLine(mainMessage)) != NULL) { 2365 /* 2366 * Some bounces include the message 2367 * body without the headers. 2368 * FIXME: Unfortunately this generates a 2369 * lot of false positives that a bounce 2370 * has been found when it hasn't. 2371 */ 2372 if((fb = fileblobCreate()) != NULL) { 2373 cli_dbgmsg("Found a bounce message with no header at '%s'\n", 2374 lineGetData(t_line->t_line)); 2375 fileblobSetFilename(fb, mctx->dir, "bounce"); 2376 fileblobAddData(fb, 2377 (const unsigned char *)"Received: by clamd (bounce)\n", 2378 28); 2379 2380 fileblobSetCTX(fb, mctx->ctx); 2381 if(fileblobScanAndDestroy(textToFileblob(t_line, fb, 1)) == CL_VIRUS) 2382 rc = VIRUS; 2383 mctx->files++; 2384 } 2385 saveIt = FALSE; ``` The line `2364 else if((t_line = encodingLine(mainMessage)) != NULL) {` return the line where the encoding is defined. In the PoC the line where the encoding is defined is the line with the body that was freed previously. This is not exploitable because the freed type `t_line *` is an structure that does not contain any function pointer that could be overwrite to control the execution. The program crashes after the UAF when the region is double freed `free(): invalid pointer: 0x000000000085d7f0`. A solution is to add a condition in mbox.c to validate that body is not NULL before looking for hiden viruses: Original: ```c 2364 else if((t_line = encodingLine(mainMessage)) != NULL) { ``` Modification: ```c 2364 else if(mainMessage->body_last != NULL && (t_line = encodingLine(mainMessage)) != NULL) { ``` This vulnerability has been found by Offensive Research at Salesforce.com: Alberto Garcia (@algillera), Francisco Oca (@francisco_oca) & Suleman Ali (@Salbei_)
Thank you very much for reporting these issues. If possible, we'd like to gather some initial first details from you on these. First, can you tell us what version of ClamAV you are reporting against? I notice that you have our git-repository name in the reports, is this a fresh check out of git?
Adding recommended fix along with a couple extra lines to set pointers to NULL after freeing them. Commit: 7cf2a701041b775dda9743d01665279facc9b326
Link to commit: https://github.com/vrtadmin/clamav-devel/commit/7cf2a701041b775dda9743d01665279facc9b326
Thank you for response and fix. Seems to work now. Jhon https://amsterdamdiary.com/