Lucene search
K

yTNEF/Evolution Directory Traversal / Buffer Overflow

🗓️ 07 Sep 2009 00:00:00Reported by Yorick KosterType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 27 Views

yTNEF/Evolution directory traversal & buffer overflow vulnerabilitie

Code
`------------------------------------------------------------------------  
yTNEF/Evolution TNEF Attachment decoder plugin directory traversal &  
buffer overflow vulnerabilities  
------------------------------------------------------------------------  
Yorick Koster, June 2009  
  
------------------------------------------------------------------------  
Abstract  
------------------------------------------------------------------------  
  
yTNEF & the Evolution TNEF Attachment decoder plugin are affected by  
several directory traversal and buffer overflow vulnerabilities. The   
directory traversal vulnerabilities allow attackers to overwrite or   
create local files with the privileges of the target user. Exploiting   
the buffer overflow vulnerabilities allows for arbitrary code execution   
with the privileges of the target user.  
  
------------------------------------------------------------------------  
See also  
------------------------------------------------------------------------  
  
- #2009-013 yTNEF/Evolution TNEF attachment decoder input sanitization   
errors [2]  
  
------------------------------------------------------------------------  
Tested version  
------------------------------------------------------------------------  
  
These vulnerabilities were discovered using the latest (stable) versions  
of Evolution (currently 2.62.2) and yTNEF (currently 2.6). The   
vulnerabilities were verified on the following Linux distributions:  
  
- GNOME version of Mandriva Linux 2009 Spring running Evolution   
2.26.1.1 (Evolution plugin installed by default)  
- Ubuntu 9.04 running Evolution 2.26.1 (with   
evolution-plugins-experimental package installed)  
  
------------------------------------------------------------------------  
Affected functions  
------------------------------------------------------------------------  
  
The following functions are affected by these issues:  
  
Evolution plugin:  
* processTnef()  
* saveVCard()  
* saveVCalendar()  
* saveVTask()  
  
yTNEF:  
* ProcessTNEF()  
* SaveVCard()  
* SaveVCalendar()  
* SaveVTask()  
  
------------------------------------------------------------------------  
Fix  
------------------------------------------------------------------------  
  
There is currently no fix available.  
  
------------------------------------------------------------------------  
Introduction  
------------------------------------------------------------------------  
  
Transport Neutral Encapsulation Format (TNEF) is a proprietary e-mail   
attachment format used by Microsoft Outlook and Microsoft Exchange   
Server. A plugin [3] for Evolution exists that provides basic support   
for TNEF encoded e-mails. This plugin uses the ytnef library [4]   
(libytnef) for processing TNEF messages. It borrows code from the ytnef   
program, which is a program to work with procmail to decode TNEF streams  
(winmail.dat attachments). Both applications share (almost) code and   
are, because of this, both affected by the issues described in this   
document.  
  
------------------------------------------------------------------------  
Evolution TNEF Attachment decoder plugin  
------------------------------------------------------------------------  
  
The plugin is started on e-mail attachments that have a MIME type of   
either application/vnd.ms-tnef or application/ms-tnef. It creates a   
temporary directory under ~/.evolution/cache/tmp using the format   
tnef-attachment-XXXXXX. The TNEF attachment is saved as   
.evo-attachment.tnef.  
  
void  
org_gnome_format_tnef(void *ep, EMFormatHookTarget *t)  
{  
[...]  
  
tmpdir = e_mkdtemp("tnef-attachment-XXXXXX");  
if (tmpdir == NULL)  
return;  
  
filepath = tmpdir;  
  
name = g_build_filename(tmpdir, ".evo-attachment.tnef",   
NULL);  
  
out = camel_stream_fs_new_with_name(name, O_RDWR|O_CREAT, 0666);  
  
  
The saved file is parsed by TNEFParseFile(), the result is stored in a   
struct of the type TNEFStruct. This struct is passed to the function   
processTnef(), which tries to extract all relevant data and attachments   
from the TNEF stream. Each relevant part of the TNEF stream is stored   
within the previously created temporary directory that are made   
available to the end user as separate e-mail attachments.  
  
/* Extracting the winmail.dat */  
TNEFInitialize(tnef);  
tnef->Debug = verbose;  
if (TNEFParseFile(name, tnef) == -1) {  
printf("ERROR processing file\n");  
}  
processTnef(tnef);  
  
TNEFFree(tnef);  
/* Extraction done */  
  
------------------------------------------------------------------------  
yTNEF  
------------------------------------------------------------------------  
  
yTNEF processes TNEF files in a similar manner. It receives a file name   
from the command line, calls TNEFParseFile() that creates a struct   
TNEFStruct after which ProcessTNEF() is called. If ProcessTNEF() finds   
attachments it can process, these attachments will be saved locally. The  
ProcessTNEF() function is almost the same as the processTnef() function  
of the Evolution plugin.  
  
int main(int argc, char ** argv) {  
[...]  
  
for(i=1; i<argc; i++) {  
[...]  
  
TNEFInitialize(&TNEF);  
TNEF.Debug = verbose;  
if (TNEFParseFile(argv[ i], &TNEF) == -1) {  
printf("ERROR processing file\n");  
continue;  
}  
ProcessTNEF(TNEF);  
TNEFFree(&TNEF);  
}  
}  
  
------------------------------------------------------------------------  
Directory traversal  
------------------------------------------------------------------------  
  
If a TNEF file is processed, both yTNEF and the Evolution plugin will   
save certain types of TNEF structures. Special processing functions are   
available for Contacts, Tasks & Appointments. These functions are   
called if the Message Class is set to a certain value.  
  
void processTnef(TNEFStruct *tnef) {  
[...]  
  
/* First see if this requires special processing. */  
/* ie: it's a Contact Card, Task, or Meeting request (vCal/vCard)   
*/  
if (tnef->messageClass[0] != 0) {  
if (strcmp(tnef->messageClass, "IPM.Contact") == 0) {  
saveVCard(tnef);  
}  
if (strcmp(tnef->messageClass, "IPM.Task") == 0) {  
saveVTask(tnef);  
}  
if (strcmp(tnef->messageClass, "IPM.Appointment") == 0) {  
saveVCalendar(tnef);  
foundCal = 1;  
}  
}  
  
if ((filename = MAPIFindUserProp(&(tnef->MapiProperties),  
PROP_TAG(PT_STRING8,0x24))) != MAPI_UNDEFINED) {  
if (strcmp(filename->data, "IPM.Appointment") == 0) {  
/* If it's "indicated" twice, we don't want to   
save 2 calendar entries. */  
if (foundCal == 0) {  
saveVCalendar(tnef);  
}  
}  
}  
  
There is also code that treats TNEF structures with the Message Class   
set to IPM.Microsoft Mail.Note. In the Evolution plugin, this code is   
never called as the global variable saveRTF is set to zero. In case of   
yTNEF this global variable is controlled by the command line.  
  
if (strcmp(TNEF.messageClass, "IPM.Microsoft Mail.Note") == 0)  
{  
if ((saveRTF == 1) && (TNEF.subject.size > 0)) {  
// Description  
if ((filename=MAPIFindProperty(&(TNEF.MapiProperties),  
PROP_TAG(PT_BINARY, PR_RTF_COMPRESSED)))  
!= MAPI_UNDEFINED) {  
[...]  
  
After the structures mentioned before have been processed, all other   
attachments are also saved locally. The file names used to save the   
attachments are obtained from the TNEF data. In case of normal   
attachments, the code first looks if the TNEF data contains MAPI   
properties and if so, it will look for specific properties. If these   
exists, a file name is extracted from these properties. If the   
properties do not exist, the attachment's title is used. This title  
is also set through a TNEF structure. If this title is also not   
available, a default file name will be used instead.  
  
if ((RealAttachment == 1) || (saveintermediate == 1)) {  
/* Ok, it's not an embedded stream, so now we */  
/* process it. */  
if ((filename = MAPIFindProperty(&(p->MAPI),   
PROP_TAG(30,0x3707)))   
== MAPI_UNDEFINED) {  
if ((filename = MAPIFindProperty(&(p->MAPI),   
PROP_TAG(30,0x3001)))   
== MAPI_UNDEFINED) {  
filename = &(p->Title);  
}  
}  
if (filename->size == 1) {  
filename = (variableLength*)malloc(sizeof(variableLength));  
filename->size = 20;  
filename->data = (char*)malloc(20);  
sprintf(filename->data, "file_%03i.dat", count);  
}  
if (filepath == NULL) {  
sprintf(ifilename, "%s", filename->data);  
} else {  
sprintf(ifilename, "%s/%s", filepath, filename->data);  
}  
for(i=0; i<strlen(ifilename); i++)   
if (ifilename[ i] == ' ')   
ifilename[ i] = '_';  
  
if ((fptr = fopen(ifilename, "wb"))==NULL) {  
printf("ERROR: Error writing file to disk!");  
} else {  
if (object == 1) {  
fwrite(filedata->data + 16,   
sizeof(BYTE),   
filedata->size - 16,   
fptr);  
} else {  
fwrite(filedata->data,   
sizeof(BYTE),   
filedata->size,   
fptr);  
}  
fclose(fptr);  
}  
}  
  
Before a new file is created, all spaces within the file name are   
replaced with the underscore character. No additional sanitation is   
performed on the file name. Because of this, it is possible to traverse   
outside of the temporary directory and create or overwrite any file with  
the privileges of the target user. This allows an attacker to execute   
arbitrary code for example by overwriting ~/.bashrc.  
  
------------------------------------------------------------------------  
Buffer overflow  
------------------------------------------------------------------------  
  
Beside the directory traversal, it is also possible to trigger a buffer   
overflow by supplying an overly long file name. This is possible,   
because the file name is copied in a fixed size buffer (256 bytes). In   
the Evolution plugin, this triggers a buffer overflow on the heap. In   
case of yTNEF the file name is copied in a buffer on the stack, thus   
allowing for a stack-based buffer overflow to occur.  
  
Evolution plugin:  
  
void processTnef(TNEFStruct *tnef) {  
[...]  
ifilename = (char *) g_malloc(sizeof(char) * 256);  
[...]  
if (filepath == NULL) {  
sprintf(ifilename, "%s", filename->data);  
} else {  
sprintf(ifilename, "%s/%s", filepath, filename->data);  
}  
  
yTNEF:  
  
void ProcessTNEF(TNEFStruct TNEF) {  
[...]   
char ifilename[256];  
[...]  
if (filepath == NULL) {  
sprintf(ifilename, "%s", filename->data);  
} else {  
sprintf(ifilename, "%s/%s", filepath, filename->data);  
}  
  
------------------------------------------------------------------------  
References  
------------------------------------------------------------------------  
  
[1] http://www.akitasecurity.nl/advisory.php?id=AK20090601  
[2] http://www.ocert.org/advisories/ocert-2009-013.html  
[3] http://www.go-evolution.org/Tnef  
[4] http://sourceforge.net/projects/ytnef/  
  
------------------------------------------------------------------------  
--   
------------------------------------------------------------------------  
Akita Software Security (Kvk 37144957)  
http://www.akitasecurity.nl/  
------------------------------------------------------------------------  
Key fingerprint = 5FC0 F50C 8B3A 4A61 7A1F 2BFF 5482 D26E D890 5A65  
http://keyserver.pgp.com/vkd/DownloadKey.event?keyid=0x5482D26ED8905A65  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation