Обновить

От чего защищает strong name в .net cборках?

.NET
Основная цель strong name или подписи сборки это ее уникальность в GAC(Global assembly cache). На основании сборки во время подписи вычисляется криптографический открытый ключ, закрытый хранится в секрете у производителя сборки, хеш-функция от которого и составляет public token, что, по сути, есть strong name для сборки. Public token сохраняется в метаданных сборки и в паре с именем сборки, версией, и культурой, и служит для уникальной ее идентификации.

Несомненно, что для уникальной идентификации сборок и использования одной и той же сборки разными приложениями такой механизм очень даже подходит.

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

Как такое возможно спросите вы? Все очень просто, так как Public token (маркер открытого ключа) зашивается в сборку то его можно просто удалить от туда.

Но ведь другие сборки, которые ссылаются на эту сборку и ее строгое имя, не загрузят ее и не будут выполняться, как следует, скажете вы. Да не загрузят. Пока они тоже подписаны строгим именем и пока в зависимостях у них указано эту сборку. Но если у этих сборок убрать строгие имена или ссылки на сборки, и заменить на те же только без строгого имени, тогда приложение отработает, как следует.

Правда следует прежде заметить, что все описанное выше работает, когда у существует доступ к сборкам для модификации. Если, например это веб-сервис то к этим сборкам нет возможности получить доступ.

Давайте рассмотрим на примере. Пусть некая компания выпускает свой продукт. Не важно какой. Важно другое, что их продукт состоит с определенного числа собственных сборок подписанных одним закрытым ключом, а следовательно с одинаковым public token. Также их продукт содержит 3rd party сборки, сборки сторонних разработчиков, компоненты, которые поставляются с продуктом. Компания решает как-то ограничить функционал продукта, естественно код ограничения и условия, при которых оно срабатывает, находятся в сборках компании. Злоумышленнику необходимо модифицировать какую-то одну сборку, чтобы снять ограничение. Он ее модифицирует и снимет строгое имя, так что сборка станет не подписанной. Чтобы другие сборки, которые ссылаются на нее, отработали правильно, он снимет подпись и с них, а также поменяет зависимости этих сборок на сборки без подписи.

Возможно, вы думаете, что сделать это сложно? Нет, сделать такое может любой школьник. Что для этого нужно? Рефлектор и плагин для него ReflexIL.

В составе ReflexIL есть strong name remover. Работает он очень просто. Выбираем сборку, жмем «Auto scan assembly directory», если будут найдены сборки со строгим именем они добавятся в список. А дальше нажимаем «Remove strong name and update referencing assemblies» и все. Теперь мы сняли подпись со сборки.

image

Т.е. не смотря на то, что нас уверяют, что строгое имя помимо отношения к глобальному кэшу сборок защищает еще и от модификации сборки, это далеко не так на практике.
Так что не стоит полагаться на строгое имя как надежную защиту от модификации.
Но как же быть спросите вы? На самом деле это уже тема другой статьи. Но ответ ясен, использовать стандартные для .NET механизмы защиты – обфускация, использование смешанного управляемого и неуправляемого кода.

Можно также проверять строгое имя сборки вручную, а в сочетании с PostSharp или каким либо другим АОП подходом, маркировать необходимые методы в коде атрибутом, сообщающим, что перед его вызовом необходимо проверить строгое имя. И проверять собственным методом строгое имя сборки с жестко зашитой константой. Только при этом куски кода с проверкой и вызовом проверки, а также константой с public token должны быть обфусцированы зашифрованы. Либо переосмыслить продукт и вынести какие-то его части в качестве веб-сервисов, хотя такое не всегда возможно. Проверить вручную строгое имя можно следующим способом.
private static bool IsPublicTokenValid(byte[] tokenExpected)
{
// Retrieve token from current assembly
byte[] tokenCurrent = Assembly.GetExecutingAssembly().GetName().GetPublicKeyToken();

// Check that lengths match
if (tokenExpected.Length == tokenCurrent.Length)
{
// Check that token contents match
for (int i = 0; i < tokenCurrent.Length; i++)
if (tokenExpected[i] != tokenCurrent[i])
return false;
}
else
{
return false;
}
return true;
}


Так от чего же защищает строгое имя? Грубо говоря, ни от чего. Это средство для уникальной идентификации сборок, с помощью которого возможно сосуществование нескольких версий одних и тех же сборок в GAC.

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

Возможно ли использовать подпись сборки строгим именем для определения автора сборки? Строгое имя не подразумевает уровень доверия к сборки, который обеспечивает, например, Authenticode.
Теги:csharpstrong nameassemblyclr
Хабы: .NET
Рейтинг +10
Количество просмотров 14k Добавить в закладки 35
Комментарии
Комментарии 28

Похожие публикации

Лучшие публикации за сутки