A brief (over)look at ClamAV security and performance. Comparing Open Source Antivirus products with commercial products.
I've been looking into signature based open source security products lately, namely Antivirus software (for SMTP E-Mail gateways or File Servers or anything that would be used as a distribution point for example as well as for Desktop systems).
I've had a pretty good look at ClamAV and other ClamAV based products (ClamWin or Spyware Terminator which include the ClamAV Engine) and found them rather weak, both from a security point of view (vulnerabilities) and in terms of detection rates, as well as performance (speed) and usability(interface, features, etc).
Clam AntiVirus (ClamAV) is an open source (GPL) anti-virus toolkit for UNIX (also ported to Windows, and used by GUI products such as ClamWin) designed especially for e-mail scanning on mail gateways. It provides a number of utilities including a flexible and scalable multi-threaded daemon, a command line scanner and advanced tool for automatic database updates. The core of the package is an anti-virus engine available in a form of shared library.
I. Security track record - a look at common vulnerabilities
So let's take a look at ClamAV's security track record. A simple look on Secunia at the vulnerability summary reveals a stunning 25 security advisories (1 unpattched), 31 % of which lead to System Access and 91 % are exploitable from remote. 40 % of vulnerabilities are "Highly Critical". I realize that some of these are in 3rd party plugins and compression tools and such, but when an attacker just sends a specially crafted archive via E-mail or whatever means, and manages to buffer overflow and gain system access when ClamAV scans it, that's when you need to look at other products. There are ways to mitigate it, with permissions, limited users, chroots, jails and such, but still...
So let's compare that with another security product, Avira Antivir, basically multi-platform Antivirus software (also has a free version for non-commercial usage). We can see only 2 security vulnerabilities reported, both local and privilege escalation (Windows only too).
Vulnerabilities range from Denial of Service: "A NULL-pointer dereference error exists within the "cli_scanrtf()" function in libclamav/rtf.c. This can potentially be exploited to crash ClamAV via a specially crafted RTF file." to Buffer Overflow and System Access: "An integer overflow error in rebuildpe.c when rebuilding PE files after unpacking can be exploited to cause a heap-based buffer overflow via a specially crafted executable. Successful exploitation of this vulnerability may allow execution of arbitrary code."
II. Vulnerability assessment tools - Static Code Analsys
What about a source code audit of ClamAV? Well, I don't really have the time for that, but I did parse it through Flawfinder, RATS and other Static Code Analysis tools looking for simple lexical "bad practices" and functions (strings functions for example) that may overflow buffers and so on.
So, I download the source code for the latest stable release: ClamAV 0.91.2 (signature) and stumble across a ton of bad programming practices. While most of the time, they mean nothing (as they aren't really vulnerabilities or even exploitable, they are usually where most errors occur, and, as such, should be avoided). We basically have hundreds of such occurrences (537 marked as High and 83 marked as Medium by RATS), so I'm just going to paste a few interesting examples here:
..\clamav-0.91.2/clamav-milter/clamav-milter.c:266: High: fixed size local buffer
Extra care should be taken to ensure that character arrays that are allocated on the stack are used safely. They are prime targets for buffer overflow attacks.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:859: High: getopt_long
Truncate all input strings to a reasonable length before passing them to this function
..\clamav-0.91.2/shared/getopt.c:961: High: fprintf
Check to be sure that the non-constant format string passed as argument 2 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle.
..\clamav-0.91.2/sigtool/vba.c:1127: High: sprintf
Check to be sure that the format string passed as argument 2 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle. Additionally, the format string could contain `%s' without precision that could result in a buffer overflow.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:1205: High: popen
Argument 1 to this function call should be checked to ensure that it does not come from an untrusted source without first verifying that it contains nothing dangerous.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:1404: High: getenv
Environment variables are highly untrustable input. They may be of any length, and contain any data. Do not make any assumptions regarding content or length. If at all possible avoid using them, and if it is necessary, sanitize them and truncate them to a reasonable length.
..\clamav-0.91.2/shared/output.c:159: High: umask
umask() can easily be used to create files with unsafe priviledges. It should be set to restrictive values.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:1585: High: gethostbyname
DNS results can easily be forged by an attacker (or arbitrarily set to large values, etc), and should not be trusted.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:1703: High: strcpy
Check to be sure that argument 2 passed to this function call will not copy more data than can be handled, resulting in a buffer overflow.
..\clamav-0.91.2/shared/misc.c:132: High: printf
Check to be sure that the non-constant format string passed as argument 1 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle.
..\clamav-0.91.2/shared/output.c:235: High: syslog
Truncate all input strings to a reasonable length before passing them to this function
..\clamav-0.91.2/freshclam/manager.c:1307: High: system
Argument 1 to this function call should be checked to ensure that it does not come from an untrusted source without first verifying that it contains nothing dangerous.
..\clamav-0.91.2/sigtool/sigtool.c:815: High: strcat
Check to be sure that argument 2 passed to this function call will not copy more data than can be handled, resulting in a buffer overflow.
..\clamav-0.91.2/libclamav/hashtab.c:408: High: sscanf
Check to be sure that the format string passed as argument 2 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle. Additionally, the format string could contain `%s' without precision that could result in a buffer overflow.
..\clamav-0.91.2/shared/options.c:194: High: strncat
Consider using strlcat() instead.
..\clamav-0.91.2/shared/options.c:194: High: strncat
Check to be sure that argument 1 passed to this function call will not copy more data than can be handled, resulting in a buffer overflow.
..\clamav-0.91.2/shared/getopt.c:983: High: getopt
Truncate all input strings to a reasonable length before passing them to this function
..\clamav-0.91.2/shared/output.c:212: High: vfprintf
Check to be sure that the non-constant format string passed as argument 2 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle.
..\clamav-0.91.2/sigtool/sigtool.c:609: High: scanf
Check to be sure that the format string passed as argument 2 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle. Additionally, the format string could contain `%s' without precision that could result in a buffer overflow.
..\clamav-0.91.2/test/pe/debugpe.c:165: Medium: signal
When setting signal handlers, do not use the same function to handle multiple signals. There exists the possibility a race condition will result if 2 or more different signals are sent to the process at nearly the same time. Also, when writing signal handlers, it is best to do as little as possible in them. The best strategy is to use the signal handler to set a flag, that another part of the program tests and performs the appropriate action(s) when it is set.
See also: http://razor.bindview.com/publish/papers/signals.txt
..\clamav-0.91.2/libclamav/mbox.c:4659: Medium: getc
Check buffer boundaries if calling this function in a loop and make sure you are not in danger of writing past the allocated space.
..\clamav-0.91.2/sigtool/sigtool.c:172: Medium: read
Check buffer boundaries if calling this function in a loop and make sure you are not in danger of writing past the allocated space.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:4260: Medium: stat
A potential TOCTOU (Time Of Check, Time Of Use) vulnerability exists. This is the first line where a check has occured. The following line(s) contain uses that may match up with this check: 4269 (open)
..\clamav-0.91.2/sigtool/vba.c:1063: Medium: realloc
Don't use on memory intended to be secure, because the old structure will not be zeroed out.
..\clamav-0.91.2/libclamav/lockdb.c:246: Medium: SetSecurityDescriptorDacl
If the third argument, pDacl, is NULL there is no protection from attack. As an example, an attacker could set a Deny All to Everyone ACE on such an object.
..\clamav-0.91.2/libclamav/msexpand.c:130: Medium: fgetc
Check buffer boundaries if calling this function in a loop and make sure you are not in danger of writing past the allocated space.
..\clamav-0.91.2/libclamav/others.c:433: Medium: srand
Standard random number generators should not be used to generate randomness used for security reasons. For security sensitive randomness a crytographic randomness generator that provides sufficient entropy should be used.
..\clamav-0.91.2/libclamav/others.c:697: Medium: lstat
A potential TOCTOU (Time Of Check, Time Of Use) vulnerability exists. This is
the first line where a check has occured.
The following line(s) contain uses that may match up with this check:
699 (rmdir), 715 (unlink)
..\clamav-0.91.2/contrib/Windows/Projects/clamAV/libclamav/regex.c:70: Medium: realloc
Don't use on memory intended to be secure, because the old structure will not be zeroed out.
You should keep in mind that ClamAV also relies on 3rd party libraries and tools, and it's security also depends on those. Again, I remind you that these aren't actual vulnerabilities, just bad practices that MAY lead to such vulnerabilities. You would need to look at the code and employ various testing tools to find them.
The authors of ClamAV should really solve these problems like OpenBSD developers do, even if it is something as simple as replacing strncat() withstrlcat() - functions designed to be safer, more consistent, and less error-prone (this would be an issue on other platforms though, so it's not as simple as that).
III. Detection rates
So, here are some tests made by various research projects:
I've been looking into signature based open source security products lately, namely Antivirus software (for SMTP E-Mail gateways or File Servers or anything that would be used as a distribution point for example as well as for Desktop systems).
I've had a pretty good look at ClamAV and other ClamAV based products (ClamWin or Spyware Terminator which include the ClamAV Engine) and found them rather weak, both from a security point of view (vulnerabilities) and in terms of detection rates, as well as performance (speed) and usability(interface, features, etc).
Clam AntiVirus (ClamAV) is an open source (GPL) anti-virus toolkit for UNIX (also ported to Windows, and used by GUI products such as ClamWin) designed especially for e-mail scanning on mail gateways. It provides a number of utilities including a flexible and scalable multi-threaded daemon, a command line scanner and advanced tool for automatic database updates. The core of the package is an anti-virus engine available in a form of shared library.
I. Security track record - a look at common vulnerabilities
So let's take a look at ClamAV's security track record. A simple look on Secunia at the vulnerability summary reveals a stunning 25 security advisories (1 unpattched), 31 % of which lead to System Access and 91 % are exploitable from remote. 40 % of vulnerabilities are "Highly Critical". I realize that some of these are in 3rd party plugins and compression tools and such, but when an attacker just sends a specially crafted archive via E-mail or whatever means, and manages to buffer overflow and gain system access when ClamAV scans it, that's when you need to look at other products. There are ways to mitigate it, with permissions, limited users, chroots, jails and such, but still...
So let's compare that with another security product, Avira Antivir, basically multi-platform Antivirus software (also has a free version for non-commercial usage). We can see only 2 security vulnerabilities reported, both local and privilege escalation (Windows only too).
Vulnerabilities range from Denial of Service: "A NULL-pointer dereference error exists within the "cli_scanrtf()" function in libclamav/rtf.c. This can potentially be exploited to crash ClamAV via a specially crafted RTF file." to Buffer Overflow and System Access: "An integer overflow error in rebuildpe.c when rebuilding PE files after unpacking can be exploited to cause a heap-based buffer overflow via a specially crafted executable. Successful exploitation of this vulnerability may allow execution of arbitrary code."
II. Vulnerability assessment tools - Static Code Analsys
What about a source code audit of ClamAV? Well, I don't really have the time for that, but I did parse it through Flawfinder, RATS and other Static Code Analysis tools looking for simple lexical "bad practices" and functions (strings functions for example) that may overflow buffers and so on.
So, I download the source code for the latest stable release: ClamAV 0.91.2 (signature) and stumble across a ton of bad programming practices. While most of the time, they mean nothing (as they aren't really vulnerabilities or even exploitable, they are usually where most errors occur, and, as such, should be avoided). We basically have hundreds of such occurrences (537 marked as High and 83 marked as Medium by RATS), so I'm just going to paste a few interesting examples here:
..\clamav-0.91.2/clamav-milter/clamav-milter.c:266: High: fixed size local buffer
Extra care should be taken to ensure that character arrays that are allocated on the stack are used safely. They are prime targets for buffer overflow attacks.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:859: High: getopt_long
Truncate all input strings to a reasonable length before passing them to this function
..\clamav-0.91.2/shared/getopt.c:961: High: fprintf
Check to be sure that the non-constant format string passed as argument 2 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle.
..\clamav-0.91.2/sigtool/vba.c:1127: High: sprintf
Check to be sure that the format string passed as argument 2 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle. Additionally, the format string could contain `%s' without precision that could result in a buffer overflow.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:1205: High: popen
Argument 1 to this function call should be checked to ensure that it does not come from an untrusted source without first verifying that it contains nothing dangerous.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:1404: High: getenv
Environment variables are highly untrustable input. They may be of any length, and contain any data. Do not make any assumptions regarding content or length. If at all possible avoid using them, and if it is necessary, sanitize them and truncate them to a reasonable length.
..\clamav-0.91.2/shared/output.c:159: High: umask
umask() can easily be used to create files with unsafe priviledges. It should be set to restrictive values.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:1585: High: gethostbyname
DNS results can easily be forged by an attacker (or arbitrarily set to large values, etc), and should not be trusted.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:1703: High: strcpy
Check to be sure that argument 2 passed to this function call will not copy more data than can be handled, resulting in a buffer overflow.
..\clamav-0.91.2/shared/misc.c:132: High: printf
Check to be sure that the non-constant format string passed as argument 1 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle.
..\clamav-0.91.2/shared/output.c:235: High: syslog
Truncate all input strings to a reasonable length before passing them to this function
..\clamav-0.91.2/freshclam/manager.c:1307: High: system
Argument 1 to this function call should be checked to ensure that it does not come from an untrusted source without first verifying that it contains nothing dangerous.
..\clamav-0.91.2/sigtool/sigtool.c:815: High: strcat
Check to be sure that argument 2 passed to this function call will not copy more data than can be handled, resulting in a buffer overflow.
..\clamav-0.91.2/libclamav/hashtab.c:408: High: sscanf
Check to be sure that the format string passed as argument 2 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle. Additionally, the format string could contain `%s' without precision that could result in a buffer overflow.
..\clamav-0.91.2/shared/options.c:194: High: strncat
Consider using strlcat() instead.
..\clamav-0.91.2/shared/options.c:194: High: strncat
Check to be sure that argument 1 passed to this function call will not copy more data than can be handled, resulting in a buffer overflow.
..\clamav-0.91.2/shared/getopt.c:983: High: getopt
Truncate all input strings to a reasonable length before passing them to this function
..\clamav-0.91.2/shared/output.c:212: High: vfprintf
Check to be sure that the non-constant format string passed as argument 2 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle.
..\clamav-0.91.2/sigtool/sigtool.c:609: High: scanf
Check to be sure that the format string passed as argument 2 to this function call does not come from an untrusted source that could have added formatting characters that the code is not prepared to handle. Additionally, the format string could contain `%s' without precision that could result in a buffer overflow.
..\clamav-0.91.2/test/pe/debugpe.c:165: Medium: signal
When setting signal handlers, do not use the same function to handle multiple signals. There exists the possibility a race condition will result if 2 or more different signals are sent to the process at nearly the same time. Also, when writing signal handlers, it is best to do as little as possible in them. The best strategy is to use the signal handler to set a flag, that another part of the program tests and performs the appropriate action(s) when it is set.
See also: http://razor.bindview.com/publish/papers/signals.txt
..\clamav-0.91.2/libclamav/mbox.c:4659: Medium: getc
Check buffer boundaries if calling this function in a loop and make sure you are not in danger of writing past the allocated space.
..\clamav-0.91.2/sigtool/sigtool.c:172: Medium: read
Check buffer boundaries if calling this function in a loop and make sure you are not in danger of writing past the allocated space.
..\clamav-0.91.2/clamav-milter/clamav-milter.c:4260: Medium: stat
A potential TOCTOU (Time Of Check, Time Of Use) vulnerability exists. This is the first line where a check has occured. The following line(s) contain uses that may match up with this check: 4269 (open)
..\clamav-0.91.2/sigtool/vba.c:1063: Medium: realloc
Don't use on memory intended to be secure, because the old structure will not be zeroed out.
..\clamav-0.91.2/libclamav/lockdb.c:246: Medium: SetSecurityDescriptorDacl
If the third argument, pDacl, is NULL there is no protection from attack. As an example, an attacker could set a Deny All to Everyone ACE on such an object.
..\clamav-0.91.2/libclamav/msexpand.c:130: Medium: fgetc
Check buffer boundaries if calling this function in a loop and make sure you are not in danger of writing past the allocated space.
..\clamav-0.91.2/libclamav/others.c:433: Medium: srand
Standard random number generators should not be used to generate randomness used for security reasons. For security sensitive randomness a crytographic randomness generator that provides sufficient entropy should be used.
..\clamav-0.91.2/libclamav/others.c:697: Medium: lstat
A potential TOCTOU (Time Of Check, Time Of Use) vulnerability exists. This is
the first line where a check has occured.
The following line(s) contain uses that may match up with this check:
699 (rmdir), 715 (unlink)
..\clamav-0.91.2/contrib/Windows/Projects/clamAV/libclamav/regex.c:70: Medium: realloc
Don't use on memory intended to be secure, because the old structure will not be zeroed out.
You should keep in mind that ClamAV also relies on 3rd party libraries and tools, and it's security also depends on those. Again, I remind you that these aren't actual vulnerabilities, just bad practices that MAY lead to such vulnerabilities. You would need to look at the code and employ various testing tools to find them.
The authors of ClamAV should really solve these problems like OpenBSD developers do, even if it is something as simple as replacing strncat() withstrlcat() - functions designed to be safer, more consistent, and less error-prone (this would be an issue on other platforms though, so it's not as simple as that).
III. Detection rates
So, here are some tests made by various research projects:
AV-Test is an anti-virus research project at the Institute of Technical and Business Information Systems at the Otto-von-Guericke University Magdeburg (Germany).
They measured the detection times for six of the malware programs released last week utilizing the MS05-039 Plug and Play vulnerability under 36 different anti-virus products. Eleven of the products were able to detect one or more of the attacks proactively, without any special pattern update to identify it specifically. Here are the numbers for each of the eleven:
Product ScoreBitDefender 6 of 6 Fortinet 6 of 6 Nod32 5 of 6 eSafe 3 of 6 F-Prot 3 of 6 Panda 3 of 6 QuickHeal 3 of 6 McAfee 2 of 6 Norman 2 of 6 AntiVir 1 of 6ClamAV 1 of 6
AV Comparatives did a test on various other Antivirus products not in their current testing process, including the ClamAV based ClamWin. Here are the results:
http://www.av-comparatives.org/seiten/ergebnisse/2ndgrouptest.pdf
This test also places ClamAV among the last in terms of detection rates:
http://www.sunbelt-software.com/ihs/alex/malwarereportjun3007.pdf
ClamAV also scores a 17 % (sig: 99% / heur: 1%) in retrospective Antivirus Performance Statistics, which also placed it among the last.
At VirusPool Tested Products ClamAV scores:
Number of descriptions in the database: 31928 out of 45159 live samples ( 70.7 %)
Number of 'in the wild' descriptions in the database: 25 out of 30 live samples ( 83.3 %)
(not very good, but not all that bad)
IV. Signature Updates:
How often is the clamav-virusdb updates? According to the FAQ, multiple times a week, and the response should be rather prompt. Anyway, to get an idea on that, take a look at http://lurker.clamav.net/list/clamav-virusdb.html
Conclusion:
I definitely need to investigate this further, but so far I find ClamAV to be highly overrated, simply based on the fact it is "part of the open source movement". It lacks a real time scanner (that's fair seeing how it was designed for mail gateways though), it has a horrible security track record, poor detection rates and dreadful performance. I somewhat doubt that it would last long as a commercial product. Still, it is available on multiple platforms, and the cost is just about right :-).
Things aren't all bad though (and I may have been to rash and only brushed the surface here). ClamAV is a free product (open source even), and it does leave a lot of room an opportunity to evolve. I just don't see this happening without powerful commercial backing. If you plan on using it though, make sure you've got at least another product scanning your emails :-).
Other links:
http://www.av-comparatives.org/
http://www.virustotal.com/