пятница, 13 августа 2010 г.

Безопасность в Active Directory. Часть 2.

Введение.
Сейчас все больше и больше развиваются Интернет-технологии, приложения Интернет-коммерции, многоуровневые и распределенные приложения.
Основной плюс таких приложений - это унифицированный интерфейс. Данный подход не требует установки клиенского приложения - пользователи работают при помощи Web-браузера.
Основная архитектура таких систем представлена на рисунке 1.1.
Рис. 1.1. Архитектура Web-приложений
Клиент, используя обозреватель Интернет, взаимодействует с Web-сервером, Web-сервер в свою очередь запрашивает данные из БД, файловых или других источников.
Примерами таких систем являются порталы Sharepoint, Forefront Identity Manager, собственные разработки на ASP.NET и т.д.

В пределах корпоративной сети, как правило используется делегирование Kerberos, тоесть Web-сервер олицетворяет клиента и использует его права для доступа к данным.

При неправильном конфигурировании Kerberos-делегирования, могут возникнуть серьезные проблемы в плане информационной безопасности.

Рассмотрим несколько возможных сценариев неправильных настроек и их последствия.

Сценарий 1. Назовем его "Классический".
В данной архитектуре у нас присутствует Web-Сервер IIS. Как правило база данных находится на другом компьютере с Microsoft SQL Server. На IIS сервере включена имперсонация, MS SQL Server использует windows-аутентификацию. Web-сервер от лица клиентов обращается за данными на MS SQL Server.
Если MS SQL и IIS находятся на разных серверах, то необходимо включить делегирование для учетной записи под которой работает IIS. И тут, как правило, системные администраторы просто включают неограниченное делегирование.
Злоумышленник может воспользоваться этим (в качестве злоумышленника может выступать и сам Web-программист, поддерживающий или разрабатывающий данный программный продукт).

Перечислим необходимые действия для получения дополнительных полномочий:
1) Включаем имперсонацию в IIS. В файл Web.config добавляем следующие строки.

<authentication mode="Windows"></authentication>
<identity impersonate="true"></identity>

Подробнее:
http://msdn.microsoft.com/en-us/library/134ec8tc(VS.80).aspx

2) Включаем делегирование для учетной записи компьютера (Пул-IIS нашего приложения запускается под учетной записью SYSTEM).
Свойство учетной записи компьютера, вкладка Delegation, галочка Trust this computer for delegation to any service (Kerberos only).

3) Используем следующий код (c#):


//Создание пользователя, добавление пользователя в группу Domain Admins
protected void Button1_Click(object sender, EventArgs e)
{
DirectoryEntry de = new DirectoryEntry("LDAP://CN=Users,DC=CONTOSO,DC=COM");
DirectoryEntry user = de.Children.Add("CN=User01", "user");
user.Properties["sAMAccountName"].Value = new object[] { "User01" };
user.CommitChanges();
user.Invoke("SetPassword", new object[] { "P@ssw0rd" });
user.InvokeSet("AccountDisabled", new object[] { false });
user.CommitChanges();
DirectoryEntry admgroup = new DirectoryEntry("LDAP://CN=Domain Admins,CN=Users,DC=CONTOSO,DC=COM");
admgroup.Invoke("Add", new object[] { user.Path });
}
//-----------------------

4) Администратор открывает страницу корпоративного портала (данный код можно повесить на загрузку страницы), выполняется код, в результате которого создается полномочная учетная запись.

Варианты решения данной проблемы:
1) Отслеживать код приложений. Данный способ крайне неудобен и сложен (можно так упрятать деструктивный код, что никто и не найдет при обзоре).
2) Не использовать делегирование и совмещать роли back-end и front-end серверов. Этот способ препятствует масштабированию.
3) Не использовать полномочные учетные записи для выполнения задач, не требующих таких полномочий. Это основное правило. Действует не только в описываемом случае. Безусловно нужно придерживаться данной рекомендации.
4) Использовать расширение протокола Kerberos - Constrained Delegation (более подробнее обсуждается далее).

Сценарий 2. Повышение полномочий.
Данный сценарий на самом деле также использует одно из расширений протокола Kerberos, появившееся в Windows Server 2003 - Protocol Transition (также можно встретить как Service-for-User-to-Self [S4U2Self]).

Подробнее - http://technet.microsoft.com/en-us/library/cc772815(WS.10).aspx

Вкратце, данное расширение позволяет без знания пароля пользователя получать Kerberos-билет и на его основе формировать маркер безопасности. Данный маркер запросившая служба использует для себя. Есть несколько режимов использования маркера - Identify и Impersonation. Первый используется для получения списка групп и полномочий пользователя (очень удобно с учетом распределенности службы Active Directory), второй можно использовать для олицетворения, локально, в системе.

Для использования режима Identify, особых условий не нужно, достаточно только сервера Windows Server 2003 и такого же уровня домена.
Для использования режима Impersonation необходимо соблюдение условий для Identify, плюс наличие полномочий "Act as part of the operating system" локальной политики безопасности. Данная привилегия по умолчанию есть у NT AUTHORITY\SYSTEM. При желании можно дать данную привилегию другой учетной записи, чего не следует делать (только если это действительно нужно).

Опишу данный сценарий по шагам:
1) У нас есть сервер IIS, на нем крутится приложение ASP.NET. Код приложения:
//отключаем делегирование (оно у меня включено в web.config)
WindowsImpersonationContext ctx = WindowsIdentity.Impersonate(IntPtr.Zero);
//Далее используем Protocol Transition
WindowsIdentity wi = new WindowsIdentity("gefimov@contoso.com");
ctx = null;
try
{
ctx = wi.Impersonate();
Response.Write("User:" + wi.User.Value);
File.Create("c:\\gefimov1\\myfile01.txt"); // Здесь полезная нагрузка, у меня просто создание файла в папке (папка находится в эксклюзивном владении - для чистоты эксперимента).
ctx.Undo();
}
catch (Exception err)
{
Response.Write("Error: " + err.Message + "");
}
//-----------------------------

Я не стал здесь правильно обрабатывать ошибки, инициализацию и освобождение. Кому интересно узнать как это правильно делается ("запросам ресурсов путем инициализации")ю необходимо обратиться к книге Бьерна Страуструпа "Язык программирования C++", второе издание, 9 глава.

2) Пул приложения IIS запущен под учетной записью, у которой есть полномочие "Act as part of the operating system".

3) В процессе выполнения кода, поток получает полномочия указанной учетной записи (в нашем случае gefimov@contoso.com), совершенно без пароля (правда какими усилиями:)).

Честно, я не встречал и не могу придумать вариант использования данного сценария (имеется ввиду, такое неправильное конфигурирование полномочий). Может быть кто-то поделится своим опытом.
Данный сценарий скорее всего является вводным для освоения следующего материала.
Тут можно извлечь лишь один урок - не давайте лишних полномочий!

Сценарий 3. Расширения Kerberos.
В данном сценарии рассказывается о получении полномочий с использованием двух расширений Kerberos, появившихся в Windows Server 2003:
1) Protocol Transition - Service-for-User-to-Self (S4U2Self) (обсуждалось выше).
2) Constrained Delegation - Service-for-User-to-Proxy (S4U2Proxy).

В общих чертах, используя два этих расширения можно 1) получать билет Kerberos без знания долгосрочного ключа пользователя (проще говоря, пароля) и при этом 2) использовать данный билет для доступа к другим службам в домене.

У данного способа есть свои ограничения (куда же без них):
1) Служба должна работать на сервере с Windows Server 2003 или выше.
2) Уровень домена должен быть Windows Server 2003.
3) Необходимо наличие прав "Act as part of operating system" (напомню что по умолчанию, это право есть у LocalSystem).
4) Необходимо настроить Kerberos Constrained Delegation для учетной записи, под которой выполняется служба.
5) Делегирование может осуществлять только в пределах локального для службы домена. Это не беда, получив права доменного админа, можно с легкостью получить права во всем лесу. (Смотрите мою первую статью про безопасность Active Directory http://gexeg.blogspot.com/2009/12/active-directory.html, также существуют другие способы, в будущем возможно опишу).

1 и 2 выполняется достаточно легко (с учетом того, что на дворе 2010 год). Получение прав для 3 случая проблем тоже не вызывает (ERD Commander и различные Live CD вам в помощь). Осталось только упросить системного администратора включить делегирование Kerberos для учетной записи компьютера или служебной учетной записи (4). Ограничение 5 приходится воспринимать как должное, тут уж никуда не денешься.
Может быть вам удастся уговорить системного администратора дать вам права "Enable computer and user accounts to be trusted for delegation" (данное полномочие позволяет владельцу учетной записи настраивать делегирование, как ему вздумается), тогда вы сами сможете настроить нужное вам делегирование.

По шагам опишу весь процесс:
1) У нас есть приложение ASP.NET на IIS (c#):
//----------
WindowsImpersonationContext ctx = WindowsIdentity.Impersonate(IntPtr.Zero);
WindowsIdentity wi = new WindowsIdentity("Administrator@contoso.com");
ctx = wi.Impersonate();
createuser(); //Создание пользователя
ctx.Undo();
//Обработка ошибок

2) Пул приложения запущен под учетной записью SYSTEM ("Act as part of operating system").
3) Для учетной записи компьютера, я настроил constrained delegation, делегируемая служба LDAP/FIM-DC01.
4) Выполняется код, происходит имперсонация и делегирование, наш поток работает с маркером Администратора домена (Administrator@contoso.com).
5) В процессе выполнения приложения, создается учетная запись пользователя и добавляется в группу Domain Admins. Миссия выполнена.

Как же этого избежать? Конечно же нужно очень трепетно относиться к делегированию.
Приведу некоторые правила:
1) Никому не давайте права "Enable computer and user accounts to be trusted for delegation".
2) Запускайте службы под учетными записями с ограниченными полномочиями (актуально для SharePoint, самому иногда было лень разбираться с доступом - запускал под SYSTEM, но конечно же не в корпоративной среде ;))
3) Ограничивайте использование полномочия "Act as part of operating system".
4) Используйте делегирование только тогда, когда это действительно нужно.
4) Используйте Constrained Delegation, при этом не указывайте службы "на всякий случай, а вдруг используется", указывайте только действительно нужные и используемые службы в делегировании.

Напоследок приведу список полезной литературы:
http://msdn.microsoft.com/en-us/library/134ec8tc(VS.80).aspx
http://gexeg.blogspot.com/2009/12/active-directory.html
http://technet.microsoft.com/en-us/library/cc772815(WS.10).aspx
http://msdn.microsoft.com/en-us/library/ff647404.aspx#paght000023_impersonatingbyusingwindowsidentity

Во вложении файл с проектом Visual Studio 2008:

MD5: DA8E5373CB6775E4F8B0C6090D67D4B7

Комментариев нет: