Юрий Спектор дата публикации 07-08-2007 02:59 Защита объектов в NT
- Пользователи и группы
- Маркер доступа
- Защита объектов, дескрипторы безопасности
- Списки контроля доступа (ACL). DACL
- Работа с ACE
- Системный список управления доступом (SACL). Аудит
- Изменение дескриптора безопасности существующего объекта. Абсолютные и отностительные дескрипторы безопасности
- Заключение
Системы линейки 9x не являются многопользовательскими в том понимании, что не позволяют разграничить доступ к ресурсам, а лишь позволяют выбрать профиль - способ отображения данных в соответствии с настройками того или иного пользователя. В системах линейки NT доступ к объектам управляется операционной системой. Защищаемыми объектами могут быть файлы, устройства, почтовые ящики, каналы, задания, процессы, потоки, объекты синхронизации, порты завершения ввода-вывода, разделы общей памяти, сетевые ресурсы, разделы реестра и др. Механизмы, о которых пойдет речь далее, применимы только к системам линейки NT.
В данной статье описаны в основном только механизмы работы. Несмотря на то, что в статье присутствуют примеры, поясняющие те или иные моменты, использующиеся в примерах функции подробно не описываются. Функций, так или иначе касающихся безопасности, очень много. Привести полный их перечень и описание в рамках данной статьи невозможно. Предполагается, что читатель умеет пользоваться справочной системой и при необходимости сможет ознакомиться с ними самостоятельно.
Как уже было сказано, Windows NT является многопользовательской системой и позволяет управлять доступом к своим объектам между несколькими потребителями. Для каждого зарегистрированного пользователя система создает учетную запись - запись, содержащую сведения о данном пользователе. Учетные записи всех пользователей хранятся в некой системной базе данных. Она представляет собой таблицу, схематически показанную на рисунке 1.
Рисунок 1. База данных учетных записей
Для каждой учетной записи система хранит имена, пароли и уникальные идентификаторы - SID (Security Identifier). Последний используется системой в дальнейшем везде, где нужно однозначно сослаться на ту или иную учетную запись. Структуру SID рассматривать не будем, можете ознакомиться самостоятельно, для нас пока важна лишь возможность с его помощью идентифицировать учетную запись.
База данных учетных записей содержит сведения не только о пользователях, но и группах пользователей (например, "Администраторы"), которые также имеют SID. Группы позволяют нескольким пользователям задать общие права доступа. Управление учетными записями с помощью групп позволяет упростить работу администратора по контролю доступа пользователей к ресурсам.
Ниже приведен фрагмент кода, позволяющий получить строковое представление SID пользователя. На входе функции нужно задать имя компьютера (пустая строка - локальный компьютер) и пользователя. Описания API приводиться не будут, вы сами сможете найти их в MSDN.
function ConvertSidToStringSid(Sid: PSID; var StringSid: PChar): BOOL;
stdcall; external advapi32 name 'ConvertSidToStringSidA';
function GetUserSIDStr(SystemName, AccountName: String): String;
var
PSID, PRef: Pointer;
SIDSize, RefSize, peUse: Cardinal;
sSID: PChar;
begin
Result:='';
SIDSize:=0;
RefSize:=0;
LookupAccountName(PChar(SystemName),PChar(AccountName),nil,SIDSize,nil,
RefSize,peUse);
GetMem(PSID,SIDSize);
GetMem(PRef,RefSize);
try
if not LookupAccountName(PChar(SystemName),PChar(AccountName),PSID,
SIDSize, PRef,RefSize,peUse) then RaiseLastOSError;
if ConvertSidToStringSid(PSID,sSID) then begin
SetLength(Result,StrLen(sSID));
StrCopy(PChar(Result),sSID);
LocalFree(Cardinal(sSID));
end;
finally
FreeMem(PRef);
FreeMem(PSID);
end;
end;
Кроме того, рекомендую самостоятельно ознакомиться с функциями GetUserName, InitializeSid, AllocateAndInitializeSid, GetSidLengthRequired, CopySid, EqualSid, FreeSid, GetLengthSid, IsValidSid, GetSidIdentifierAuthority, GetSidSubAuthority, GetSidSubAuthorityCount, LookupAccountSid, ConvertStringSidToSid, CreateWellKnownSid.
Теперь давайте рассмотрим, что происходит, когда пользователь входит в систему. После успешной проверки подлинности имени пользователя и пароля система создает так называемый маркер доступа (Access token). Маркер доступа представляет собой объект, который содержит кроме всего прочего SID пользователя, прошедшего аутентификацию, и SID групп, в которые этот пользователь входит.
Рисунок 2. Аутентификация.
Для каждого процесса, созданного данным пользователем, система создает копию маркера доступа и прикрепляет ее к процессу. Маркер доступа является как бы пропуском, удостоверяющим личность пользователя, создавшего процесс.
Кроме SID пользователя и групп, маркер доступа содержит и другие элементы, (такие как список привилегий, например). В рамках данной статьи они рассматриваться не будут.
А сейчас приведем код, позволяющий получить маркер доступа текущего процесса и извлечь из него список SID пользователя и групп, в которые он входит.
type
PTokenUser = ^_TOKEN_USER;
_TOKEN_USER = record
User : TSidAndAttributes;
end;
function SIDToStr(SID: PSID): String;
var
sSID: PChar;
begin
Result:='';
if ConvertSidToStringSid(SID,sSID) then begin
SetLength(Result,StrLen(sSID));
StrCopy(PChar(Result),sSID);
LocalFree(Cardinal(sSID));
end;
end;
procedure GetSIDStrList(List: TStringList);
var
hToken, Len: Cardinal;
pTU: PTokenUser;
pTG: PTokenGroups;
i: Integer;
begin
List.Clear;
if not OpenProcessToken(GetCurrentProcess,TOKEN_QUERY,hToken) then
RaiseLastOSError;
try
GetTokenInformation(hToken,TokenUser,nil,0,Len);
GetMem(pTU,Len);
try
if not GetTokenInformation(hToken,TokenUser,pTU,Len,Len)
then RaiseLastOSError;
List.Add(SIDToStr(pTU^.User.Sid));
finally
FreeMem(pTU);
end;
GetTokenInformation(hToken,TokenGroups,nil,0,Len);
GetMem(pTG,Len);
try
if not GetTokenInformation(hToken,TokenGroups,pTG,Len,Len) then
RaiseLastOSError;
for i:=0 to pTG^.GroupCount - 1 do begin
List.Add(SIDToStr(pTG^.Groups[i].Sid));
end;
finally
FreeMem(pTG);
end;
finally
CloseHandle(hToken);
end;
end;
В данном коде упрощена проверка ошибок, чтобы не загромождать его лишними вызовами. По-хорошему, при получении размеров буферов нужно проверять код ошибки на равенство ERROR_INSUFFICIENT_BUFFER. Если код ошибки другой, то ее причина не связана с недостаточным размером буфера.
С помощью функции GetTokenInformation можно получить и другие параметры маркера доступа. С ее возможностями вы сможете ознакомиться самостоятельно, как и с другими функциями, работающими с маркером доступа.
Переходим непосредственно к защите объектов. На данном этапе, вы должны знать, что пользователи и группы идентифицируются с помощью SID, и каждый процесс в системе знает, от чьего имени он выполняется - эта информация содержится в маркере доступа процесса. Как уже было сказано, маркер доступа представляет собой что-то вроде пропуска, теперь давайте выясним, кому этот пропуск нужно предъявлять.
Для того чтобы ограничить доступ к объекту, его нужно снабдить дескриптором безопасности (Security descriptor). Это и есть тот охранник, стоящий на страже объекта и не пропускающий к нему никого чужого. Дескриптор безопасности представляют собой структуру следующего вида:
_SECURITY_DESCRIPTOR = record
Revision: Byte;
Sbz1: Byte;
Control: SECURITY_DESCRIPTOR_CONTROL;
Owner: PSID;
Group: PSID;
Sacl: PACL;
Dacl: PACL;
end;
Несмотря на то, что дескриптор безопасности - это структура, работать напрямую ее полями не следует. Нужно использовать специальные функции, которые будут рассмотрены чуть позже. А пока ознакомимся с полями этой структуры. Поле Revision - это номер версии, на данный момент может иметь только значение SECURITY_DESCRIPTOR_REVISION. Sbz1 служит для выравнивания и должно содержать нули. Control - набор флагов, описывающих свойства дескриптора безопасности. Owner - SID владельца объекта. Владелец объекта имеет право изменять настройки доступа к объекту, даже если в это явно запретить в DACL (см. далее). SID первичной группы (параметр Group) нужен исключительно для совместимости со стандартом POSIX. Поля Sacl и Dacl являются указателями на соответствующие списки контроля доступа, которые для нас (особенно DACL) представляют наибольшее значение. Чуть позже мы перейдем к более подробному их обсуждению, а пока рассмотрим некоторую ситуацию.
Допустим, мы пишем серверное приложение, выполняющееся под системной учетной записью, и нам нужно создать объект (например, событие Event), который будут совместно использовать и наш сервер, и клиенты, выполняющиеся под учетными записями пользователей. Для этого в первую очередь нужно присвоить объекту имя и поместить его в глобальное пространство имен, чтобы другие пользователи могли его увидеть.
hEvent:=CreateEvent(nil,true,false,'Global\evMyServerObject');
Однако если мы попытаемся получить дескриптор этого объекта с помощью OpenEvent в приложении, выполняющемся под ограниченной учетной записью, мы получим отказ в доступе. Почему? Потому что мы не задали атрибуты безопасности для этого объекта (первый параметр) и не указали в них дескриптор безопасности. В результате, система создала объект и назначила ему дескриптор безопасности по умолчанию, который открывает полный доступ только создателю объекта и всем членам группы администраторов, а остальным - закрывает.
А как система узнала, что мы не имеем права доступа к этому объекту? Наверняка она проверила наш пропуск (маркер доступа) и на этом основании сделала вывод, что мы права доступа к объекту не имеем. А где написано, кто имеет доступ к объекту, а кто не имеет? Ответ - эта информация записана в дескрипторе защиты, а именно - в одном из его списках контроля доступа.
Как видно из структуры дескриптора безопасности, он содержит два поля, содержащих в своем названии 'ACL' (Access-Control List) - список контроля доступа. Таких списков два: Discretionary Access-Control List, (DACL) - список управления избирательным доступом и System Access-Control List (SACL) - системный список управления доступом. Их структура схожа, однако они выполняют совершенно разные функции. В данном разделе будет более подробно рассмотрен DACL, так как он имеет для нас наибольшее значение. Именно DACL формирует правила, кому разрешить доступ к объекту, а кому - запретить. Поэтому все, что будет сказано о списках контроля доступа и его элементах, в большей степени относится именно к DACL. SACL позволяет лишь управлять аудитом (об этом - ниже).
Каждый список контроля доступа (ACL) представляет собой набор элементов контроля доступа (Access Control Entries, или ACE). Чтобы не было путаницы в терминах, изобразим схематически (рисунок 3).
Рисунок 3. ACL и ACE
ACE бывает двух типов (разрешающий и запрещающий доступ) и обязательно содержит три поля:
- SID пользователя или группы, к которому применяется данное правило
- Вид доступа, на которое распространяется данное правило
- Тип ACE - разрешающий или запрещающий.
Таким образом, ACL, изображенный на рисунке 3, (если это не просто ACL, а DACL) устанавливает следующие правила: пользователю SID1 разрешить доступ на чтение объекта, но запретить доступ на запись, а пользователю SID2 - разрешить полный доступ к объекту.
Кроме того, к дескриптору безопасности применимы следующие правила:
- Если DACL отсутствует, то объект считается незащищенным, т.е. все имеют к нему неограниченный доступ.
- Если DACL существует, но не содержит ни одного ACE, то доступ к объекту закрыт для всех.
Возвращаясь к примеру из прошлого раздела, покажем, как нужно было создать событие, доступ к которому может иметь любой пользователь.
var
sa: TSecurityAttributes;
sd: TSecurityDescriptor;
hEvent: THandle;
begin
InitializeSecurityDescriptor(@sd,SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(@sd,true,nil,false);
sa.nLength:=SizeOf(TSecurityAttributes);
sa.lpSecurityDescriptor:=@sd;
sa.bInheritHandle:=false;
hEvent:=CreateEvent(@sa,true,false,'Global\evMyServerObject');
Система сопоставляет маркер доступа и дескриптор защиты не при каждом обращении к объекту, а только при получении его дескриптора (рисунок 4). Например, если имеется защищенный объект-мьютекс, система проверяет права только при вызове процессом функции OpenMutex. В этой же функции процесс сразу же указывает, какие виды доступа ему в дальнейшем потребуются. Если все указанные виды доступа разрешены - процесс получает дескриптор объекта и может его использовать сколь угодно долго в соответствии с запрошенными правами. Даже если DACL объекта изменится. После того как процесс получил дескриптор, система не сможет его забрать. Если же система принимает решение отказать в доступе, процесс просто не получит дескриптор объекта.
Рисунок 4. Запрос доступа к объекту.
Таким образом, продолжая аналогию, дескриптор безопасности - это охранник, маркер доступа - это пропуск, а DACL - это приказ охраннику, кому давать доступ, а кому - отказывать.
Ну и в заключение главы отметим, что ядро обращается к объектам не через дескрипторы, а через указатели. Права доступа в режиме ядра не проверяются, другими словами, система полностью сама себе доверяет и всегда имеет доступ к объекту.
Рассмотрим такую ситуацию. А что, если два ACE противоречат друг другу? Например, один ACE дает полный доступ членам определенной группы, а другой - запрещает доступ определенному пользователю из этой группы. Получит ли этот пользователь доступ к объекту? А это зависит от того, в каком порядке ACE расположены.
Когда процесс запрашивает определенный вид доступа к защищенному дескриптором безопасности объекту, система действует по следующему алгоритму:
- Извлекает маркер доступа процесса, в котором содержится SID пользователя и групп, в которые он входит.
- Просматриваются все ACE в DACL дескриптора безопасности от первого к последнему.
- Определяющую роль играет первый встреченный элемент, дающий возможность пользователю воспользоваться запрошенной услугой или отказывающий в этом.
- Если хотя бы один из видов запрошенного доступа не предоставлен (запрещен или достигнут конец DACL), система принимает решение отказать в доступе к объекту. Из этого можно сделать вывод, что запрещающие элементы не имеет смысла размещать внизу DACL, так как если перед ними нет соответствующих разрешающих, доступ все равно будет закрыт. Запрещающие элементы обычно размещают вверху списка. Особенно если нужно запретить доступ конкретному пользователю, который может его получить, воспользовавшись членством в группе.
Чтобы было понятнее, поясним на примере. Допустим, процесс, запущенный от имени пользователя User1, входящего в группу Group1, запрашивает доступ к объекту на чтение и запись. DACL дескриптора безопасности объекта имеет следующий вид:
Учетная запись |
Вид доступа |
Разрешить, запретить |
User1 |
чтение |
разрешить |
Group1 |
запись |
разрешить |
User1 |
запись |
запретить |
Доступ к объекту с таким DACL на чтение и запись будет разрешен, несмотря на последний элемент. Так как проход по DACL начинается сверху вниз, а первый элемент предоставит право на чтение, а второй - на запись. На этом система и остановится. А если последний элемент поместить наверх, то доступ будет запрещен.
А теперь поставим обратную задачу: в системе зарегистрировано 5 пользователей: User1..User5. User1 и User2 входят в группу Group1. User3, User4 и User5 входят в группу Group2. Необходимо составить такой DACL, который:
- Дает полный доступ к объекту всем членам группы Group1.
- Дает доступ только на чтение всем членам группы Group2.
- Не дает никакого доступа пользователю User5.
DACL будет выглядеть, например, так:
Учетная запись |
Вид доступа |
Разрешить, запретить |
User5 |
полный доступ |
запретить |
Group2 |
чтение |
разрешить |
Group1 |
полный доступ |
разрешить |
Теперь на небольшом примере продемонстрируем работу с DACL и его элементами. Создадим небольшое приложение, которое по нажатию на одну кнопку запускает процесс (Windows-калькулятор) и назначает ему дескриптор защиты, разрешающий всем пользователям любой вид доступа, кроме PROCESS_TERMINATE (доступ на завершение процесса). По нажатию на другую кнопку, попробуем получить дескриптор этого процесса, затребовав запрещенный вид доступа. Если все сделать правильно, на экране появится окошко, сообщающее об отказе в доступе. Сразу скажу, что для простоты в данном примере опущена всяческая обработка ошибок, однако в "боевых" приложениях не стоит ее игнорировать.
function CreateWellKnownSid(WellKnownSidType: Cardinal; DomainSid, Sid: PSID;
var cbSID: Cardinal): Bool; stdcall; external advapi32 name 'CreateWellKnownSid';
const
WinWorldSid = 1;
aclSize = 1024;
ACL_REVISION = 2;
var
pi: TProcessInformation;
procedure TForm1.Button1Click(Sender: TObject);
var
si: TStartupInfo;
sa: TSecurityAttributes;
sd: TSecurityDescriptor;
dacl: PACL;
SID: PSID;
SIDLength: Cardinal;
begin
InitializeSecurityDescriptor(@sd,SECURITY_DESCRIPTOR_REVISION);
GetMem(dacl,aclSize);
try
InitializeAcl(dacl^,aclSize,ACL_REVISION);
SIDLength:=0;
CreateWellKnownSid(WinWorldSid,nil,nil,SIDLength);
GetMem(SID,SIDLength);
try
CreateWellKnownSid(WinWorldSid,nil,SID,SIDLength);
AddAccessAllowedAce(dacl^,ACL_REVISION,PROCESS_ALL_ACCESS and
not PROCESS_TERMINATE,SID);
SetSecurityDescriptorDacl(@sd,true,dacl,false);
sa.nLength:=SizeOf(TSecurityAttributes);
sa.lpSecurityDescriptor:=@sd;
sa.bInheritHandle:=false;
FillChar(si,SizeOf(TStartupInfo),0);
si.cb:=SizeOf(TStartupInfo);
CreateProcess('C:\WINDOWS\system32\calc.exe',nil,@sa,nil,false,0,
nil,nil,si,pi);
CloseHandle(pi.hThread);
finally
FreeMem(SID);
end;
finally
FreeMem(dacl);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
hProcess: Cardinal;
begin
hProcess:=OpenProcess(PROCESS_TERMINATE,false,pi.dwProcessId);
if hProcess = 0 then
RaiseLastOSError
else
TerminateProcess(hProcess,0);
end;
В примере используется функция CreateWellKnownSid. С помощью нее мы получаем указатель на SID группы 'everyone' (SID этой группы всегда один и тот же - S-1-1-0), которая включает всех пользователей. Эта функция в данном случае мне показалась наиболее простой и удобной, однако на системах младше XP работать не будет. Вы можете использовать другой способ, например, с помощью AllocateAndInitializeSid.
Кроме функции для работы с ACL и ACE, использующихся в примере, рекомендую самостоятельно ознакомиться с AddAccessDeniedAce, AddAce, DeleteAce, GetAce, GetAclInformation, IsValidAcl, SetAclInformation, SetEntriesInAcl.
Дескриптор безопасности содержит указатель на System Access-Control List (SACL) - список, похожий на DACL, но отвечающий не за разрешение или запрет на доступ, а за аудит (протоколирование в журнале безопасности) успешных и безуспешных попыток доступа к объекту. Благодаря системе аудита, администратор может узнать, кто, каким образом и когда пользовался (или пытался пользоваться, но получил отказ в доступе) интересующими его ресурсами. Для работы с SACL используются как общие для всех ACL функции, так и специфичные - AddAuditAccessAce, AddAuditDeniedAce, GetSecurityDescriptorSacl, SetSecurityDescriptorSacl.
В данной главе мы вернемся к примеру с процессом, защищенным от завершения, попытаемся снять это ограничение и завершить его. А заодно познакомимся с функциями, позволяющими получать и изменять дескриптор безопасности уже существующего объекта.
Для того чтобы изменить DACL объекта, процесс должен обладать правом WRITE_DAC, однако, во-первых, мы не запрещали его в DACL (PROCESS_ALL_ACCESS включает это право), а даже если бы запретили - оно все равно у нас было бы на правах владельца (поле Owner в дескрипторе безопасности), так как владелец всегда имеет право изменять DACL.
Для получения дескриптора безопасности процесса можно воспользоваться функцией GetKernelObjectSecurity. Но использование этой функции порождает некоторые проблемы. Дело в том, что при вызове функции InitializeSecurityDescriptor, получается так называемый абсолютный (absolute) дескриптор безопасности. Свое название такой тип получил из-за того, что указатели, содержащиеся в нем, представляют собой абсолютный адрес в памяти процесса и указывают на структуры памяти, не входящие в сам дескриптор. При связывании дескриптора с объектом, система объединяет все данные, относящиеся к дескриптору в одну компактную структуру. Такой тип дескриптора называется самоопределяющийся относительный (self-relative). Название данный тип получил из-за того, что указатели в нем теперь содержат не абсолютный адрес, а относительное смещение элемента в данной структуре. Такой тип дескриптора удобен, если его нужно сбросить в какое-либо хранилище, (например - в файл) или переслать по сети. Также файловая система NTFS хранит дескриптор безопасности для каждого файла или папки именно в таком формате. Проверить формат дескриптора можно с помощью GetSecurityDescriptorControl.
Когда мы вызываем GetKernelObjectSecurity (или другие подобные функции), система возвращает именно относительный дескриптор. Многие функции, такие как SetSecurityDescriptorDacl, требуют дескриптор безопасности именно в абсолютном формате. Имеются специальные функции, позволяющие преобразовывать дескриптор из одной формы в другую (MakeAbsoluteSD, MakeSelfRelativeSD), однако их использование делает код очень громоздким (функция MakeAbsoluteSD имеет 11 параметров!). Другая неприятность заключается в том, что для работы с разными типами объектов нужно использовать разные функции: для объектов ядра, таких как процесс, поток, мьютекс и др. - Get(Set)KernelObjectSecurity, для файлов - Get(Set)FileSecurity, для user-объектов - Get(Set)UserObjectSecurity, для ключей реестра - RegGet(Set)KeySecurity и др.
К счастью, у этих проблем есть одно простое и элегантное решение - функции GetSecurityInfo и SetSecurityInfo. Их можно использовать на системах, начиная от NT 4.0. Для того чтобы продемонстрировать преимущества этих функций, напишем с их помощью код, снимающий запрет на завершение процесса. В модуле Windows.pas этих функций нет (по крайней мере, на Delphi 7), можете импортировать их самостоятельно или воспользоваться заголовочными файлами JEDI API - http://jedi-apilib.sourceforge.net/.
Итак, бросаем на форму из примера с защищенным процессом еще одну кнопку и прописываем ей такой обработчик щелчка:
uses JwaAclApi, JwaAccCtrl;
procedure TForm1.Button3Click(Sender: TObject);
var
hProcess: Cardinal;
begin
hProcess:=OpenProcess(WRITE_DAC,false,pi.dwProcessId);
if hProcess <> 0 then begin
SetSecurityInfo(hProcess,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,
nil,nil,nil,nil);
CloseHandle(hProcess);
end
else
RaiseLastOSError;
end;
Вот и все. В функции SetSecurityInfo мы просто устанавливаем объекту nil в качестве DACL. Для сравнения, без использования этой функции нам нужно было бы:
- С помощью GetKernelObjectSecurity получить дескриптор безопасности (относительный). Причем функцию пришлось бы вызывать два раза - один для получения размера буфера, второй - для получения самого дескриптора.
- Вызвать функцию MakeAbsoluteSD для получения размеров буферов для DACL, SACL, SID и GROUP.
- Выделить память под эти элементы.
- Еще раз вызвать MakeAbsoluteSD для преобразования дескриптора в абсолютный формат.
- С помощью SetSecurityDescriptorDacl установить nil в качестве DACL.
- Вызовом SetKernelObjectSecurity установить объекту новый дескриптор безопасности.
- Освободить память, выделенную в п.1. и п.2.
Даже не буду пытаться привести код для сравнения, так как выигрыш при использовании SetSecurityInfo очевиден. Хотя, именно в данном случае можно было не получать установленный объекту дескриптор и преобразовывать его в абсолютный, а создать новый с нуля. Однако в большинстве случаев нужно сохранить многие параметры существующего дескриптора, которые заранее неизвестны.
Теперь запускаем пример на выполнение. Щелкаем сначала на первую кнопку - создаем процесс, затем на вторую - получаем отказ в доступе, на третью - снимаем с процесса защиту, и снова вторую - вуаля! Процесс завершился.
Хочу также обратить ваше внимание еще на две функции, подобные SetSecurityInfo и GetSecurityInfo - SetNamedSecurityInfo и GetNamedSecurityInfo. Их основное отличие от упомянутых ранее в том, что вместо дескриптора объекта нужно указать его имя.
В данной статье были рассмотрены основные принципы защиты объектов на системах линейки NT. Многие моменты, такие как запуск процессов от имени другой учетной записи, олицетворение или имперсонация (выполнение отдельных потоков процесса от имени другой учетной записи), привилегии (особые полномочия, перечисленные в маркере доступа, предоставляющие их владельцам исключительные права на доступ к объектам, а также позволяющие выполнять привилегированные операции) и многие другие, не были рассмотрены, однако надеюсь, что изложенный в статье материал поможет вам самим при необходимости с ними разобраться.
Благодарности: SLoW - за советы, конструктивную критику и просто поддержку при написании данной статьи.
[Безопасность системы]
Обсуждение материала [ 08-11-2008 00:17 ] 7 сообщений |