Эта небольшая статья посвящена одной из структур данных операционной системы,
с которой связаны операции управления учетными записями, контроля доступа,
аудита и другие функции безопасности Windows.
Эта структура носит имя SID (
Security Identifier).
Согласно описанию из Platform SDK, SID - это структура данных переменной длины,
которая идентифицирует учетную запись пользователя, группы или компьютера.
Каждой учетной записи ставится в соответствие уникальный идентификатор, SID,
в момент создания учетной записи.
Система оперирует с SID'ами учетных записей, а не их именами.
Дискреционные списки контроля доступа (DACL) хранят SID'ы учетных записей
(пользователей и групп) и права доступа, назначенные этим учетным записям,
чтобы обеспечивать контроль доступа к защищаемым объектам.
При открытии объекта программа пользователя запрашивает требуемые права
доступа к объекту, а подсистема контроля доступа ОС сопоставляет данные
в DACL с запрошенными правами и SID'ом пользователя,
от имени которого исполняется программа (учитывается также
членство пользователя в группах, SID'ы которых также присоединены
к контексту безопасности программы).
Для контроля доступа операционной системе имена учетных записей
не требуются - идентификация учетных записей происходит по SID'ам.
Уникальность SIDа обеспечивается его образованием из двух полей:
AUTHORITY и
SUBAUTHORITY.
Первое поле имеет фиксированную длину и определяет класс учетной записи,
второе поле имеет переменную длину и идентифицирует учетную запись внутри
класса. Поле SUBAUTHORITY может иметь нулевую длину,
в этом случает SID идентифицирует класс учетных записей.
В Platform SDK структура SID определяется следующим образом:
typedef struct _SID {
BYTE Revision;
BYTE SubAuthorityCount;
SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
DWORD SubAuthority[1];
} SID, *PISID;
Revision - версия SID. Это поле должно быть равно константе
SDK SID_REVISION (1).
SubAuthorityCount - количество слов (DWORD'ов) в поле
SubAuthority.
IdentifierAuthority - поле AUTHORITY.
SubAuthority - поле SUBATHORITY.
Согласно описанию структуры SID, AUTHORITY представляется как
структура
SID_IDENTIFIER_AUTHORITY, определенная в Platform SDK
следующим образом:
typedef struct _SID_IDENTIFIER_AUTHORITY {
BYTE Value[6];
} SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY;
Таким образом, AUTHORITY представляется последовательностью из 6 байт.
В Platform SDK определены константы для инициализации значения
SID AUTHORITY при построении или анализе SID:
#define SECURITY_NULL_SID_AUTHORITY {0,0,0,0,0,0}
#define SECURITY_WORLD_SID_AUTHORITY {0,0,0,0,0,1}
#define SECURITY_LOCAL_SID_AUTHORITY {0,0,0,0,0,2}
#define SECURITY_CREATOR_SID_AUTHORITY {0,0,0,0,0,3}
#define SECURITY_NON_UNIQUE_AUTHORITY {0,0,0,0,0,4}
#define SECURITY_NT_AUTHORITY {0,0,0,0,0,5}
#define SECURITY_RESOURCE_MANAGER_AUTHORITY {0,0,0,0,0,9}
Кроме того, существует ещё один, недокументированный в Platform SDK AUTHORITY:
#define SECURITY_INTERNET_AUTHORITY {0,0,0,0,0,7}
Эти константы можно использовать, например, при инициализации объявленного
экземпляра структуры:
SomeFunction()
{
SID_IDENTIFIER_AUTHORITY Authority = SECURITY_NT_AUTHORITY;
}
SUBAUTHORITY - поле, переменной длины, состоящее из слов (DWORD'ов),
количество которых хранится в структуре SID. Объявление поля в структуре как:
DWORD SubAuthority[1];
позволяет обращаться к любому DWORD'у в SubAuthority, не прибегая к
приведению указателей. Но при этом размер структуры SID без
SUBAUTHORITY должен вычисляться как
(sizeof(SID) - sizeof(DWORD))
т.к. в структуре объявлен один DWORD поля SUBAUTHORITY.
Ранее отмечалось, что минимальная длина SUBAUTHORITY - 0 слов.
Максимальная длина определяется константой Platform SDK
SID_MAX_SUB_AUTHORITIES (15).
Максимальный размер (в байтах), необходимый для хранения SID,
можно вычислить следующим образом:
((sizeof(SID) - sizeof(DWORD)) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES)
Если известно количество слов в SUBAUTHORITY, то размер SID можно
вычислить следующим образом:
((sizeof(SID) - sizeof(DWORD)) + sizeof(DWORD)*SubAuthorityCount)
Для отображения бинарных данных SID'ов,
их можно представлять в виде строки следующего формата:
S-R-I-s-s...
где:
S - неизменный идентификатор строкового представления SID;
R -
SID_REVISION (1);
I - значение SID AUTHORITY;
s - значения слов поля SUBAUTHORITY. В строковом представлении
каждая s соответствует одному DWORD'у из SUBATHORITY
SID группы "Администраторы" для локального компьютера в виде
строки выглядит следующим образом:
S-1-5-32-544
В этой записи:
1 -
SID_REVISION;
5 - значение AUTHORITY (соответствует
SECURITY_NT_AUTHORITY);
32 - значение первого слова SUBAUTHORITY;
544 - значение второго слова SUBAUTHORITY.
Количество слов в SUBAUTHORITY - 2.
SID учетной записи "ВСЕ" ("Everyone") в виде строки
выглядит следующим образом:
S-1-1-0
В этой записи:
1 -
SID_REVISION;
1 - значение AUTHORITY (соответствует
SECURITY_WORLD_SID_AUTHORITY);
0 - значение первого слова SUBAUTHORITY.
Количество слов в SUBAUTHORITY - 1.
SID учетной записи "Псевдодомен NT" ("NT Pseudo Domain") в виде строки
выглядит следующим образом:
S-1-5
В этой записи:
1 -
SID_REVISION;
5 - значение AUTHORITY (соответствует
SECURITY_NT_AUTHORITY);
Количество слов в SUBAUTHORITY - 0.
SID некоторого пользователя локального компьютера в виде строки
может выглядеть следующим образом:
S-1-5-21-789336058-484763869-725345543-1003
В этой записи:
1 -
SID_REVISION;
5 - значение AUTHORITY (соответствует
SECURITY_NT_AUTHORITY);
21 - значение первого слова SUBAUTHORITY;
789336058 - значение второго слова SUBAUTHORITY;
484763869 - значение третьего слова SUBAUTHORITY;
725345543 - значение четвертого слова SUBAUTHORITY;
1003 - значение пятого слова SUBAUTHORITY.
Количество слов в SUBAUTHORITY - 5.
В системе существует специальный SID для обозначения идентификатора
сессии (
logon SID).
Этот SID можно использовать в списках контролях доступа для
контроля доступа к объектам пользователей, интерактивно работающих в системе
в текущий момент.
SID идентификатора сессии существует, пока пользователь не вышел из системы.
При каждом новом входе в систему генерируется другой
logon SID.
Права доступа для
Logon SID установлены на оконную станцию WinSta0,
отображающую окна пользовательских программ во время его сеанса работы в
системе. При запуске графической программы от имени другого пользователя,
следует добавлять права доступа на оконную станцию для
Logon SID'а
этого пользователя, для того, чтобы окна программы могли отображаться.
Эти действия выполняются при запуске процесса от имени другого
пользователя функцией
CreateProcessAsUser.
Знание структуры SID позволяет выявить список встроенных учетных записей
Windows. Для получения списка следует в цикле заполнить поля структуры
SID и попытаться получить имя учетной записи, для которой был заполнен SID
(с помощью
LookupAccountName, возвращающей имя учетной записи по SID).
Список полученных таким образом встроенных учетных записей в
разных Windows приведен в таблице.
Встроенные учетные записи Windows
SID Имя 2000 XP 2003 VISTA
S-1-0-0 NULL SID - + + +
S-1-1-0 Все
Everyone + + + +
S-1-2-0 ЛОКАЛЬНЫЕ
LOCAL + + + +
S-1-3-0 СОЗДАТЕЛЬ-ВЛАДЕЛЕЦ
CREATOR OWNER + + + +
S-1-3-1 ГРУППА-СОЗДАТЕЛЬ
CREATOR GROUP + + + +
S-1-3-2 СОЗДАТЕЛЬ-ВЛАДЕЛЕЦ СЕРВЕР
CREATOR OWNER SERVER + + + +
S-1-3-3 ГРУППА-СОЗДАТЕЛЬ СЕРВЕР
CREATOR GROUP SERVER + + + +
S-1-5 Псевдодомен NT
NT Pseudo Domain + + + +
S-1-5-1 УДАЛЕННЫЙ ДОСТУП
DIALUP + + + +
S-1-5-2 СЕТЬ
NETWORK + + + +
S-1-5-3 ПАКЕТНЫЕ ФАЙЛЫ
BATCH + + + +
S-1-5-4 ИНТЕРАКТИВНЫЕ
INTERACTIVE + + + +
S-1-5-6 СЛУЖБА
SERVICE + + + +
S-1-5-7 АНОНИМНЫЙ ВХОД
ANONYMOUS LOGON + + + +
S-1-5-8 PROXY + + + +
S-1-5-9 КОНТРОЛЛЕРЫ ДОМЕНА ПРЕДПРИЯТИЯ
ENTERPRISE DOMAIN CONTROLLERS + + + +
S-1-5-10 SELF + + + +
S-1-5-11 Прошедшие проверку
Authenticated Users + + + +
S-1-5-12 ОГРАНИЧЕННЫЕ
RESTRICTED + + + +
S-1-5-13 ПОЛЬЗОВАТЕЛЬ СЕРВЕРА ТЕРМИНАЛОВ
TERMINAL SERVER USER + + + +
S-1-5-14 REMOTE INTERACTIVE LOGON - + + +
S-1-5-15 Данная организация
This Organization - - + +
S-1-5-17 IUSR - - - +
S-1-5-18 SYSTEM + + + +
S-1-5-19 LOCAL SERVICE - + + +
S-1-5-20 NETWORK SERVICE - + + +
S-1-5-22 КОНТРОЛЛЕРЫ ДОМЕНА ПРЕДПРИЯТИЯ,
ДОСТУПНЫЕ ТОЛЬКО ДЛЯ ЧТЕНИЯ ДЛЯ
БЕТА ВЕРСИИ - - - +
S-1-7 Internet$ + + + +
S-1-16 Обязательная метка - - - +
S-1-16-0 Ненадежный обязательный уровень - - - +
Для управления SID программисты Microsoft предусмотрели несколько
функций (см. таблицу).
Функции для управления SID'ами
Назначение Функция из ntdll.dll Функция из advapi32.dll
(недокументирована в PSDK) (документирована в PSDK)
Выделяет память и
инициализирует SID RtlAllocateAndInitializeSid AllocateAndInitializeSid
Переводит SID в
строковую форму
представления RtlConvertSidToUnicodeString ConvertSidToStringSid
Копирует SID RtlCopySid CopySid
Сравнивает два SID'а
без учета последнего
слова в SUBATHORITY RtlEqualPrefixSid EqualPrefixSid
Сравнивает два SID'а RtlEqualSid EqualSid
Освобождает память,
выделенную при инициа-
лизации SID'а соответ-
ствующей функцией RtlFreeSid FreeSid
Возвращает значение
AUTHORITY для SID RtlIdentifierAuthoritySid GetSidIdentifierAuthority
Инициализирует SID RtlInitializeSid InitializeSid
Вычисляет необходимый
размер памяти для
хранения SID RtlLengthRequiredSid GetSidLengthRequired
Возвращает размер SID RtlLengthSid GetLengthSid
Возвращает количество
слов в SUBATHORITY RtlSubAuthorityCountSid GetSidSubAuthorityCount
Возвращает все слова
SUBATHORITY RtlSubAuthoritySid GetSidSubAuthority
Проверяет SID на
корректность RtlValidSid IsValidSid
Переводит SID из
строковой формы пред-
ставления в бинарную ConvertStringSidToSid
Создает SID встроенной
учетной записи CreateWellKnownSid
Проверяет, является ли
указанный SID иденти-
фикатором встроенной
учетной записи IsWellKnownSid
Сравнивает два SID'а
и выявляет, принадлежат
ли учетные записи с
этими SID'ами одному
домену EqualDomainSid
При написании этой статьи были замечены некоторые особенности в работе
функций по управлению SID'ами.
Например, функция IsValidSid проверяет поле
Revision не полностью,
а только младшие четыре байта и считает верными SID'ы с установленными
в поле
Revision значениями такими как 0x41, 0xF1 и т.д.
При этом функция
ConvertSidToStringSid переводит в строку только SID'ы
с "правильным"
Revision, равным 0x01.
Функция
ConvertSidToStringSid некорректно переводит в строковую форму
SID'ы, содержащие ненулевые значения в первых двух байтах AUTHORITY.
Например, для двух SID'ов с пустым SUBAUTHORITY и AUTHORITY равным
{0,1,0,0,0,0} для первого SID'а, {0,0,0,0,0,10} - для второго SID'а,
строка, возвращенная функцией, будет одинакова: "
S-1-10".
AddAccessAllowedAce позволяет добавить в DACL запись с неверным
SID (в SID неверным является поле
Revision, равное например, 0x41).
Но установить SECURITY DESCRIPTOR с таким DACL на объект невозможно
(функция установки прав доступа возвращает ошибку, указывая на неверный
формат данных). Но
AddAccessAllowedAce запрещает создавать записи
контроля доступа с SID, если в
Revision неверны 4 младших бита
(например,
Revision равен 0x0F).
Ссылки:
Access Control Overview
Basic Access Control Functions