Insufficient argument validation of hooked SSDT functions on multiple Antivirus and Firewalls

Insufficient argument validation of hooked SSDT functions on multiple Antivirus and Firewalls


Core Security Technologies - CoreLabs Advisory

http://www.coresecurity.com/corelabs/

Advisory Information

Title: Insufficient argument validation of hooked SSDT functions on multiple Antivirus and Firewalls
Advisory ID: CORE-2008-0320
Advisory URL: http://www.coresecurity.com/?action=item&id=2249
Date published: 2008-04-28
Date of last update: 2008-04-28
Vendors contacted: BitDefender, Comodo, Sophos and Rising
Release mode: Coordinated release (BitDefender, Comodo, Rising), User release (Sophos)

Vulnerability Information

Class: Invalid memory reference
Remotely Exploitable: No
Locally Exploitable: Yes
Bugtraq Name: 28741, 28742, 28743, 28744
CVE Name: CVE-2008-1735, CVE-2008-1736, CVE-2008-1737, CVE-2008-1738

Vulnerability Description

Insufficient argument validation of hooked SSDT functions on multiple Antivirus and Firewalls
(BitDefender Antivirus [1],
Comodo Firewall [2],
Sophos Antivirus [3] and
Rising Antivirus [4])
have been found that could lead to a Denial of Service (DoS) and possibly to code execution attacks.
An attacker, utilizing these flaws, could be able to locally reboot the whole system shutting down the firewall or
anti-virus protection. However, in some cases it may be possible to extend the impact of these bugs,
and they could lead to the execution of arbitrary code in the privileged kernel mode.

Vulnerable packages

  • BitDefender Antivirus 2008 Build 11.0.11
  • Comodo Firewall Pro 2.4.18.184
  • Sophos Antivirus 7.0.5
  • Rising Antivirus 19.60.0.0 and 19.66.0.0
  • Older versions may be affected, but were not checked.

Non-vulnerable packages

  • BitDefender Antivirus 2008 builds available through automatic updates, posterior to January 18th.
  • Comodo Firewall Pro 3.0
  • Rising Antivirus 20.38.20

Vendor Information, Solutions and Workarounds

1) BITDEFENDER ANTIVIRUS (BID 28741, CVE-2008-1735)

According to BitDefender, the flaw was not exploited
by any malicious application, and it was corrected through automatic
updates. Information on this issue can be found on BitDefender website at this location:
http://kb.bitdefender.com/KB419-en--Security-vulnerability-in-BitDefender-2008.html.


2) COMODO FIREWALL PRO (BID 28742, CVE-2008-1736)

The vulnerability is fixed in Comodo Firewall Pro 3.0, available at:
http://www.personalfirewall.comodo.com/download_firewall.html


3) SOPHOS ANTIVIRUS (BID 28743, CVE-2008-1737)

Vendor statement:

"Sophos Anti-Virus 7.x for Windows 2000, 2003 and XP is affected by this
vulnerability.

Non-vulnerable products from Sophos are earlier versions of Sophos
Anti-Virus for Windows, Sophos Anti-Virus for non-Windows platforms and
all other Sophos products.

The vulnerability is only exploitable if Runtime Behavioural Analysis is
switched on.
Even then the exploit will only be effective if the end user is using
security settings that are lower than the defaults for most web browsers
today, or if the end user agrees to activate an ActiveX or Java Applet
from the webpage hosting the exploit.

Workarounds to avoid this vulnerability include:

a. Using the default security settings or higher on the latest version of
your chosen web browser. In line with general security best practice we
would also encourage end users not to download ActiveX or Java Applets
unless confident about their content.

b. Turning off the Runtime Behavioural Analysis functionality within Sophos
Anti-Virus (customers will still benefit from Sophos Behavioural
Genotype protection and other means of protecting endpoints against
malware).

N.B. Should an exploit be released into the wild, Sophos will deploy
protection against that exploit.

The fix for this vulnerability requires customers to reboot their
endpoints. Given the low severity of the vulnerability, to minimise
disruption to our customers Sophos will release the fix at the earliest
opportunity that coincides with a necessary reboot of the product."


4) RISING ANTIVIRUS (BID 28744, CVE-2008-1738)

A fixed version of Rising Antivirus can be downloaded from:
http://rsdownload.rising.com.cn/for_down/rsfree/ravolusrfree.exe

All Rising customers can also update up to a patched version through automatic updates.

Credits

These vulnerabilities (except the Rising one) were discovered by Damian Saura, Anibal Sacco,
Dario Menichelli, Norberto Kueffner, Andres Blanco y Rodrigo Carvalho from Core Security Technologies,
during Bugweek 2007.
The Rising vulnerability was discovered by Anibal Sacco from Core Security Technologies exploit writers team.

These vulnerabilities were researched by Anibal Sacco and Damian Saura from Core Security Technologies.

Technical Description / Proof of Concept Code

We have found that BitDefender Antivirus, Rising Antivirus, Comodo Firewall and Sophos Antivirus have hooks that
do not properly validate the arguments of the hooked functions before accessing them,
and lead to the program trying to reference some invalid memory, leading in some scenarios
to a BSOD (Blue Screen of Death).

In our tests we used the kernel hooks probing tool BSODhook
[5]
in order to find any kind of insufficient argument validation of hooked SSDT functions.
From Matousec paper [6]:

"Hooking kernel functions by modifying the System Service Descriptor Table (SSDT)
is a very popular method of implementation of additional security features and
is used frequently by personal firewalls and other security and low-level software.
Although undocumented and despised by Microsoft, this technique can be implemented
in a correct and stable way. However, many software vendors do not follow the rules
and recommendations for kernel-mode code writing and many drivers that implement
SSDT hooking do not properly validate the parameters of the hooking functions."

"Hooking SSDT functions requires extra caution. SSDT function handlers are executed
in the kernel mode but their callers are executed in the user mode. Hence all function
arguments come from the user mode. This is why it is necessary to validate these
arguments properly. Otherwise a simple user call can easily crash the whole system.
This bug usually results in a system crash. However, it may happen that this bug is
even more dangerous and may lead to the execution of an arbitrary code in the privileged
kernel mode."

A local DoS attack, despite not being a very sophisticated intrusion attack,
could be used as an accessory under several scenarios. It is commonly
used by viruses as added feature, when the specific AV is detected on
the infected machine, crashing the system just to annoy. Or by a human
attacker, after a succesful remote intrusion with unprivileged
credentials to make a computer resource unavailable to its intended
users. Besides, this could be a very valuable resource when trying to
fake some service that answers broadcasts request like a DHCP, allowing
to start the service in another location replacing the original one.


1) BITDEFENDER ANTIVIRUS (BID 28741, CVE-2008-1735)

BitDefender fails to validate the pointer to the CLIENT_ID structure
provided to NtOpenProcess. So, if we pass an invalid pointer,
we will crash the whole system.

NtOpenProcess(PHANDLE ProcessHandle,
ACCESS_MASK AccessMask,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId )

.text:00010ADE  push    0Ch
.text:00010AE0  push    offset stru_114E8
.text:00010AE5  call    __SEH_prolog
.text:00010AEA  call    KeGetCurrentThread
.text:00010AEF  xor     ebx, ebx
.text:00010AF1  cmp     [eax+140h], bl
.text:00010AF7  jz      short loc_10B0D
.text:00010AF9  call    PsGetCurrentProcessId
.text:00010AFE  call    PsGetCurrentProcessId
.text:00010B03  push    eax
.text:00010B04  call    sub_10724
.text:00010B09  test    eax, eax
.text:00010B0B  jnz     short loc_10B12
.text:00010B0D
.text:00010B0D loc_10B0D:                   ; CODE XREF: sub_10ADE+19_j
.text:00010B0D  push    [ebp+ClientId]
.text:00010B10  jmp     short loc_10B73
.text:00010B12 ; ---------------------------------------------------------------------------
.text:00010B12
.text:00010B12 loc_10B12:                   ; CODE XREF: sub_10ADE+2D_j
.text:00010B12  mov     edi, [ebp+ClientId]
.text:00010B15  cmp     edi, ebx            ; Little check to avoid a Null Pointer

Here it gets the pointer to the ClientId value,
and if it is non zero (!= 0) it does not care where
it is pointing to.

.text:00010B17  jnz     short loc_10B1C
.text:00010B19  push    ebx
.text:00010B1A  jmp     short loc_10B73
.text:00010B1C ; ---------------------------------------------------------------------------
.text:00010B1C
.text:00010B1C loc_10B1C:                   ; CODE XREF: sub_10ADE+39_j
.text:00010B1C  mov     [ebp+ms_exc.disabled], ebx
.text:00010B1F  mov     esi, [edi]          ; Here it crashes
    

It access to that memory, and if that is invalid memory the system will crash.

.text:00010B21                 mov     [ebp+var_1C], esi
.text:00010B24                 or      [ebp+ms_exc.disabled], 0FFFFFFFFh
.text:00010B28                 jmp     short loc_10B3B
.text:00010B28 sub_10ADE       endp


2) COMODO FIREWALL PRO (BID 28742, CVE-2008-1736)

In Comodo there are problems in the arguments validation of NtDeleteFile,
NtCreateFile and NtSetThreadContext functions.
NtDeleteFile receives just one parameter, a pointer to an
OBJECT_ATTRIBUTES structure. These attributes would include the
ObjectName and the SECURITY_DESCRIPTOR, for example.
This is the hook placed by Comodo at NtDeleteFile.

NTDeleteFile (POBJECT_ATTRIBUTES ObjectAttributes)

.text:0001ACB0  push    1Ch
.text:0001ACB2  push    offset stru_1E3F0
.text:0001ACB7  call    __SEH_prolog
.text:0001ACBC  xor     ebx, ebx
.text:0001ACBE  inc     ebx
.text:0001ACBF  mov     [ebp+var_1C], ebx
.text:0001ACC2  xor     esi, esi
.text:0001ACC4  mov     [ebp+var_24], esi
.text:0001ACC7  mov     [ebp+var_20], ebx
.text:0001ACCA  mov     [ebp+var_28], esi
.text:0001ACCD  mov     [ebp+ms_exc.disabled], esi
.text:0001ACD0  call    ds:ExGetPreviousMode
.text:0001ACD6  mov     edi, [ebp+ObjectAttributes]
    

Here it does a lot of ProbeForRead checks to see if the pointers of the
structure are valid. Nice! (EDI still has a pointer to the
OBJECT_ATTRIBUTES structure)

....
.text:0001AD25  push    edi             ; ObjectAttributes
.text:0001AD26  call    sub_1A692       ; Here it passes the OBJECT_ATTRIBUTES structure pointer to the next function.

sub_1A692
.text:0001A692  push    28h
.text:0001A694  push    offset stru_1E3C0
.text:0001A699  call    __SEH_prolog
.text:0001A69E  xor     edi, edi
....
.text:0001A6B3  mov     [ebp+ms_exc.disabled], edi
.text:0001A6B6  push    72747052h       ; Tag
.text:0001A6BB  mov     ebx, 400h
.text:0001A6C0  push    ebx             ; NumberOfBytes
.text:0001A6C1  push    1               ; PoolType
.text:0001A6C3  call    ds:ExAllocatePoolWithTag  ; Allocates memory to hold the data retrieved by ZwQueryObject
.text:0001A6C9  mov     esi, eax
.text:0001A6CB  mov     [ebp+var_28], esi
.text:0001A6CE  cmp     esi, edi
.text:0001A6D0  jz      short loc_1A74F

.text:0001A6D2  mov     edi, [ebp+ObjectAttributes]
.text:0001A6D5  mov     eax, [edi+OBJECT_ATTRIBUTES.RootDirectory] ; Here, the code retrieves the RootDirectory's field value from the structure, controled by us.
.text:0001A6D8  test    eax, eax
.text:0001A6DA  jz      short loc_1A71B

.text:0001A6DC  push    0               ; ReturnLength
.text:0001A6DE  push    ebx             ; ObjectInformationLength
.text:0001A6DF  push    esi             ; ObjectInformation
; buffer where ZwQueryObject will put the object information

.text:0001A6E0  push    1               ; ObjectInformationClass
; Specifies an OBJECT_INFORMATION_CLASS value that determines the type
; of information returned in the ObjectInformation buffer. It's using
; an undocumented type (OBJECT_NAME_INFORMATION) which returns an UNICODE_STRING structure
.text:0001A6E2  push    eax             ; ObjectHandle
; Now, the user-controlled handle 'll be used here to identify the object by ZwQueryObject,
.text:0001A6E3  call    ds:ZwQueryObject
.text:0001A6E9  mov     [ebp+var_20], eax
.text:0001A6EC  test    eax, eax
.text:0001A6EE  jl      short loc_1A746
    

Here is where the problem shows up. The code does not properly validates the
data retrieved by ZwQueryObject, expecting an
UNICODE_STRING structure. But it is possible to make multiple
calls to the function using different handlers to obtain a null structure crashing the system when
the code tries to dereference its Buffer field.

.text:0001A6F0  movzx   eax, [esi+UNICODE_STRING.Length]
.text:0001A6F3  shr     eax, 1
.text:0001A6F5  mov     ecx, [esi+UNICODE_STRING.Buffer]
.text:0001A6F8  movzx   eax, word ptr [ecx+eax*2-2] ; Here is the problem
.text:0001A6FD  mov     [ebp+var_30], eax
.text:0001A700  cmp     ax, 5Ch
.text:0001A704  jz      short loc_1A725
    


3) SOPHOS ANTIVIRUS (BID 28743, CVE-2008-1737)

Insufficient argument validation of hooked SSDT functions on Sophos lead
to a DoS. An attacker, utilizing this flaw, would be able to locally reboot
the whole system shutting down the
Firewall or AV protection. Although neither the vendor nor Core Security
has found a means of exploiting the flaw to execute arbitrary code, it has
not been possible to rule this out.

In Sophos AV there is a problem in the arguments validation of NtCreateKey function.

int __cdecl NtCreateKeyHook(PHANDLE pKeyHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
ULONG TitleIndex,PUNICODE_STRING Class,
ULONG CreateOptions,
PULONG Disposition)

[...]
.text:0001C01C  push    4               ; Alignment
.text:0001C01E  push    18h             ; Length
.text:0001C020  mov     esi, [ebp+ObjectAttributes]
.text:0001C023  push    esi             ; Address
.text:0001C024  call    ds:ProbeForRead

Here it checks for ObjectAttributes to be pointing to a valid address.

.text:0001C02A  mov     eax, [esi+OBJECT_ATTRIBUTES.RootDirectory]
.text:0001C02D  mov     [ebp+Handle], eax
.text:0001C030  mov     esi, [esi+OBJECT_ATTRIBUTES.ObjectName]
.text:0001C033  mov     [ebp+pUnicodeString], esi

Now, it gets from OBJECT_ATTRIBUTES a handle and a pointer
to an UNICODE_STRING structure.

.text:0001C095  push    4
.text:0001C097  push    8
.text:0001C099  push    esi
.text:0001C09A  mov     ebx, ds:ProbeForRead
.text:0001C0A0  call    ebx             ; ProbeForRead, it checks the pointer before the dereference.

.text:0001C0A2  mov     eax, dword ptr [esi+UNICODE_STRING.Length]
.text:0001C0A4  mov     dword ptr [ebp+stUnicodeString.Length], eax
.text:0001C0A7  mov     esi, [esi+UNICODE_STRING.Buffer]   ; And gets from the UNICODE_STRING structure
; a pointer to the unicode buffer.
.text:0001C0AA  mov     [ebp+stUnicodeString.Buffer], esi
.text:0001C0AD  push    2               ; Alignment
.text:0001C0AF  shr     eax, 10h
.text:0001C0B2  push    eax             ; Length
.text:0001C0B3  push    esi             ; Address
.text:0001C0B4  call    ebx             ; ProbeForRead

It does the check, but here is the problem

.text:0001C0B6  push    gdwValue
.text:0001C0BC  lea     eax, [ebp+stUnicodeString]
.text:0001C0BF  push    eax
.text:0001C0C0  push    [ebp+Object]
.text:0001C0C3  call    sub_1cb40

The problem relies in the function not properly checking the
Length field of the UNICODE_STRING
structure. When doing the check, ProbeForRead receives the length
field of the structure as a parameter without any kind of validation.

So, if we set this field to 0, ProbeForRead will not
raise any exception even though we were passing it an invalid address.
And it will crash when trying to access to the desired invalid memory.

sub_1cb40

[...]
.text:0001CB5E  xor     esi, esi
.text:0001CB60  mov     [ebp+ms_exc.disabled], esi
.text:0001CB63  mov     edi, [ebp+pUnicodeString]
.text:0001CB66  mov     eax, [edi+UNICODE_STRING.Buffer]

And here is where it will crash:

.text:0001CB69  cmp     word ptr [eax], '\'  ; Reference the first pointed byte


4) RISING ANTIVIRUS (BID 28744, CVE-2008-1738)

In Rising antivirus the code of the NtOpenProcess
hook does not validates if the pointer to the structure

typedef struct _CLIENT_ID {
HANDLE  UniqueProcess;
HANDLE  UniqueThread;}
    

is really pointing to mapped memory. So, when the code tries to dereference the pointer
to check the CLIENT_ID->UniqueProcess value, if it is pointing
to invalid memory, will crash.

NtOpenProcess( OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId )

.text:00010EAA  push    ebp
.text:00010EAB  mov     ebp, esp
.text:00010EAD  push    esi
.text:00010EAE  mov     esi, offset Addend
.text:00010EB3  push    edi
.text:00010EB4  mov     ecx, esi            ; Addend
.text:00010EB6  call    ds:InterlockedIncrement
.text:00010EBC  call    PsGetCurrentProcessId
.text:00010EC1  cmp     eax, dword_11C8C
.text:00010EC7  jnz     short loc_10ECE
.text:00010EC9
.text:00010EC9 loc_10EC9:                   ; CODE XREF: sub_10EAA+37_j
.text:00010EC9  push    [ebp+ClientId]
.text:00010ECC  jmp     short loc_10EF0
.text:00010ECE ; ---------------------------------------------------------------------------
.text:00010ECE
.text:00010ECE loc_10ECE:                   ; CODE XREF: sub_10EAA+1D_j
.text:00010ECE  call    PsGetCurrentProcessId
.text:00010ED3  mov     ecx, dword_11C80
.text:00010ED9  push    eax
.text:00010EDA  call    sub_11070
.text:00010EDF  test    al, al
.text:00010EE1  jnz     short loc_10EC9
.text:00010EE3  call    PsGetCurrentProcessId
.text:00010EE8  mov     edi, [ebp+ClientId] ; Here is the bug, if ClientId is pointing to an invalid address
.text:00010EEB  cmp     eax, [edi]	        ; it will crash.
.text:00010EED  jnz     short loc_10F0D
    

Report Timeline

  • 2008-01-11: Core Security Technologies found a security vulnerability in BitDefender antivirus.
  • 2008-01-14: BitDefender team is contacted by Core.
  • 2008-01-15: BitDefender team asks Core for technical description of the vulnerability.
  • 2008-01-15: Technical details are sent to BitDefender team by Core.
  • 2008-01-22: BitDefender notifies Core that a fix has been produced and the flaw was corrected through automatic updates.
  • 2008-02-04: According to the original schedule, the CORE-2008-0320 advisory would be released at this date, but similar flaws in other antivirus products were discovered by Core exploit writers team. Considering all BitDefender users are patched, Core Security Technologies does not release the advisory and continues the research of this issue in other products.
  • 2008-03-20: Core analyzes similar vulnerabilities in Comodo Firewall, Sophos Antivirus and Rising Antivirus.
  • 2008-03-25: Core notifies the Comodo, Sophos and Rising teams of the vulnerabilities.
  • 2008-03-27: Comodo team asks Core for technical description of the vulnerability.
  • 2008-03-27: Technical details are sent to Comodo team by Core.
  • 2008-03-31: Rising team asks Core for technical description of the vulnerability.
  • 2008-04-01: Technical details are sent to Rising team by Core.
  • 2008-04-02: Rising team inform Core that the flaw has been fixed in the Rising AV 2008 version.
  • 2008-04-02: Sophos team asks Core for technical description of the vulnerability.
  • 2008-04-07: Technical details are sent to Sophos team by Core.
  • 2008-04-11: Sophos team informs that the flaw is found in one of the antivirus drivers, and fixing it will require a reboot for all of Sophos Windows customers. Sophos would like to fix the bug in the next major version (second quarter 2009), in particular considering the fact that they were unable to come up with any practical use of this vulnerability.
  • 2008-04-14: Comodo notifies Core that a fix has been produced.
  • 2008-04-14: Sophos informs Core that they will be able to release a fix to the vulnerability at the end of October 2008.
  • 2008-04-21: Core responds that they will reschedule the publication to April 24th, 2008. Since the vulnerability is not critical, and has been found using publicly available tools, like the other vulnerabilities included in the advisory, Core doesn't see a reason to postpone the publication of the Sophos bug until October 2008.
  • 2008-04-21: Sophos asks Core not to release details of the vulnerability until a fix is available, and not to publish Proof of Concept code. Sophos informs that they do not believe that arbitrary code execution is possible.
  • 2008-04-24: Core responds that the advisory does not contain Proof of Concept code. Core confirms its intention of publishing the advisory, including the technical description, but decides to postpone it to April 28th, to give the participants more time to coordinate the release of public information.
  • 2008-04-25: Sophos provides additional information, included in the "vendor information" section of the advisory.
  • 2008-04-28: CORE-2008-0320 advisory is published.

References


[1] http://www.bitdefender.com


[2] http://www.comodo.com

[3] http://www.sophos.com

[4] http://www.rising-global.com

[5] http://www.matousec.com/downloads


[6] http://www.matousec.com/info/articles/plague-in-security-software-drivers.php

About CoreLabs

CoreLabs, the research center of Core Security Technologies, is charged with anticipating the future needs
and requirements for information security technologies. We conduct our research in several important areas
of computer security including system vulnerabilities, cyber attack planning and simulation, source code auditing,
and cryptography. Our results include problem formalization, identification of vulnerabilities, novel solutions
and prototypes for new technologies. CoreLabs regularly publishes security advisories, technical papers,
project information and shared software tools for public use at: http://www.coresecurity.com/corelabs/.

About Core Security Technologies

Core Security Technologies develops strategic solutions that help security-conscious organizations worldwide
develop and maintain a proactive process for securing their networks. The company's flagship product,
CORE IMPACT, is the most comprehensive product for performing enterprise security assurance testing.
CORE IMPACT evaluates network, endpoint and end-user vulnerabilities and identifies what resources are exposed.
It enables organizations to determine if current security investments are detecting and preventing attacks.
Core Security Technologies augments its leading technology solution with world-class security consulting services, including penetration
testing and software security auditing. Based in Boston, MA and Buenos Aires, Argentina, Core Security Technologies
can be reached at 617-399-6980 or on the Web at http://www.coresecurity.com.

Disclaimer

The contents of this advisory are copyright (c) 2008 Core Security Technologies and (c) 2008 CoreLabs,
and may be distributed freely provided that no fee is charged for this distribution and proper credit is given.

PGP/GPG Keys

This advisory has been signed with the GPG key of Core Security Technologies advisories team, which is
available for download at /legacy/files/attachments/core_security_advisories.asc.

Locally Exploitable: 
no
Remotely Exploitable: 
no
  • Request Info

Research Blog