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

    Основная цель 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.
    Реклама
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее

    Комментарии 28

      +2
      пожалуйста, перенесите статью в блог .net
        0
        перенесено
        0
        >Строгое имя не может защитить от подмены сборки
        неверное утверждение. попробуйте модифицировать System.dll и вы поймете в чем проблема.

        подписанные сборки защищены от подмены. Тот факт, что можно снять подпись и подкорректировать все остальные сборки не дает права говорить что защиты нет. Она есть и её можно сломать.
          0
          Модификация CLR сборок отдельная тема, можно конечно им все поудалять строгое имя. Но там помимо строгого имени есть цифровая подпись.

          Но зачем из них удалять строгое имя? Код приложения там не содержится, смысла делать это нет. Есть смысл удалять строгое имя со сборок приложения.

          Проверьте насколько они защищены, напитсав простое приложеньеце из нескольких сборок и попробовав модифицировать код сборок. Не хотел добавлять в текст банальный пример консольного приложения с сателитной сборкой.
            0
            Вот нашел ссылочку для Вас
              0
              Насчет защищены от подмены — почитайте мой комментарий — ничего удалять нигде не надо.
              0
              Это как утверждать, что «дверные замки не защищают от воровства т.к. вор может установить свой замок и беспрепятственно проникать в жилище»
                +1
                Вы сравниваете не соизмеримые вещи
                +2
                модифицировать можно и без удаления подписи, существует ключик в реестре HKLM\SOFTWARE\Microsoft\StrongName\Verification\*,71E9BCE111E94*** (ваш отпечаток в общем)… собственно добавляете и среда не станет проверять подпись (аналогично это же делает утилита sn с ключем -Vr)
                  0
                  Да, согласен, но пример с -Vr (ну и реестром, это ведь одно и то же по сути) будет отклонять проверку только на локальной машине. При удалении строгого имени и соотв. атрибута из сборки — на любой. Собственно, как написал mezastel ниже.
                  +1
                  Чтобы посмотреть как обходить подписывание, можно глянуть на Reflexil — там можно просто внести сборку в список «освобожденных от проверок» сборок (через командную строку тоже можно), и всё — сборку никто больше не будет проверять. Другое дело что это работает только локально.

                  Аналогия с вором: вы не можете обворовывать чужих, но можете красть у тех, кто живет с вами.

                  Млин… бредовая аналогия получилась. Ну вы поняли…
                    –1
                    Только у меня осталось впечатление о плохом переводе, потере слов и прочих ужасах текста из Promt?
                      +1
                      Вот вам сервис
                      www.copyscape.com

                      найдете не мою копию на любом языке, удалю статью и принесу извенения.

                      Статью писал сам и исследовал этот вопрос так как коллеги заблуждались по поводу строгого имени. Как оказалось не только они одни.

                      Если есть предложения по поводу стиля, грамматики, ошибок и прочего литературного охотно их расмотрю и внесу правки
                        0
                        1)Несомненно, что для уникальной идентификации сборок и использования одной и той же сборки разными приложениями такой механизм очень даже подходит.
                        Наверное, нужно говорить, идентификации уникальности, а не уникальной идентификации.
                        2)

                          0
                          Блин, хабр скушал остальное, что писал
                          2)Важно другое, что в случае строгое имя не защитит сборку от модификации, как многие думают, и соответственно механизм в CLR не отработает, как положено и загрузит модифицированную сборку.
                          Вам не кажется, что после или перед словом «случае», чего-то не хватает?
                          3)Пока они тоже подписаны тем же строгим и пока в зависимостях у них указано связь со сборкой со строгим именем.
                          Тем же строгим чем?
                          Короче можно так еще ооочень долго продолжать, это еще без проверки орфографии, и расстановки знаков препинания!
                        0
                        >Т.е. не смотря на то, что нас уверяют, что строгое имя помимо отношения к глобальному кэшу сборок защищает еще и от модификации сборки, это далеко не так на практике.
                        На практике нужно предпринять некоторые дополнительные действия, чтобы это работало. Во-первых, защитить сам EXE от модификации (например, Hasp Envelope — согласен, подходит далеко не во всех случаях, но для embedded — самое то), во-вторых, перед загрузкой сборки или в Program.Main проверять данный ключ реестра на наличие токенов, которых там быть не должно. И действовать соответсвенно.
                          0
                          Вот кстати нарыл еще — есть API функция StrongNameSignatureVerificationEx, с помощью которой можно принудительно выполнить проверку подписи, несмотря на записи в реестре для этой сборки. Можно вызывать перед загрузкой плагинов и пр. (требует P/Invoke).
                            0
                            Про то что сборку нужно обфусцировать и криптовать я упомянул, также то что неплохо было бы вручную проверять строгое имя в разных частях сборки тоже.

                            Про принуительную проверки не писал так как это из разряда «ручная проверка».

                            Хотя абсолютно согласен было бы неплохо так делать перед загрузкой плагинов, только сами плагины, если они от 3-х разработчиков тогда должны как-то сообщать программе их действительные а не поддельные строгие имена, так как в данном случае строгие имена плагинов и программы не обязаны совпадать.
                              0
                              Строгое имя можно вывести из метаданных. Public key там есть, а токен из него можно получить не очень сложно.
                                0
                                Я не то имел в виду. Естественно можно.

                                Я имел в виду то что есть издатель приложения. Он подписывает сборку своими ключами. Плагины могут разрабатывать сторонние разработчики. У них другие ключи. Издатель приложения свой закрытый ключ им не даст. Т.е. подпись строгим именем у плагина будет другая. Плагин может создать издатель плагина, а может и злоумышленник изменив его и внедрив код и подписав своим ключом. Т.е. для основного приложения стоит задача отделить две неизвестные ему подписи и определить «правильную» сборку по токенам.

                                В таком случае наверное может помочь механизм регистрации плагина у издателя основного приложения. В таком случае издатель внесет строгое имя в какой-то свой список чтобы распознать плагин от его злонамеренной модификации.
                          0
                          Если я не спутал, то эта тема чуть ли не пять лет назад поднималася на Codeproject.com, а изначально я прочитал её перевод (всех трёх частей) в Компьютерной газете. Собственно, статья: www.codeproject.com/KB/security/NeCoder01.aspx
                            0
                            Глянул спасибо, только вы немного ошиблись ссылкой, про строгие имена во второй части не нашел там. Но там автор подает это как механизм защиты. Я же утверждаю и написал статью именно для того чтобы избежать подобных заблуждения.

                            А вот про то что можно удалить строгие имена легко нашел в третьей части www.codeproject.com/KB/security/NeCoder03.aspx. Судя по всему автор пересмотрел свое мнение от первой-второй части до третьей

                            Строгие имена — это не надежный механизм защиты от модификации сборки и основное предназначение их не в этом. А вообще эта тема возникла тогда когда возникли строгие имена с .NET — так что я думаю и автор на кодпроджекте и я не первые и не последние, потому что например во 2-ой редакции рихтера, насколько я помню, строгие исена подаются как, дополнительно, механизм защиты от модификации. Хотя там не говорится насколько надежный и упоминается оговорка про цифровые подписи и Autheticode

                            0
                            Ваша статья сломала мне мозг.
                              +2
                              Чтобы снять проверку на strong name для конкретной сборки можно также просто выполнить команду:
                              sn.exe -Vr имясборки.dll
                                +1
                                Да можно и так, только тогда проверка на соответствие строгого имени сборки не будет проходить только на локальной машине. А вот если полностью удалить строгое имя — тогда на любой.

                                Ключ -Vr делает запись в реестре, см коммент habrahabr.ru/blogs/net/91999/#comment_2781797
                                +2
                                Спасибо, вы усилили мою паранойю.
                                  0
                                  >На основании сборки во время подписи вычисляется криптографический открытый ключ

                                  Может что то поменялось с прошлой неделе, но каким местом криптографический ключ то да еще на основании сборки, да еще и во время подписи вычисляется? Может все таки _перед_ подписью генерится ключевая пара? А то, что вы называете «на основании» имеется в виду как хэш от сборки, подписанный закрытым ключом?
                                    0
                                    От чего защищает бумажка со штампом на опечатанной двери?
                                    Ведь
                                    1) Кто угодно может сорвать её.
                                    2) Кто угодно может наклеить бумажку с надписью «Здесь был Вася» вместо неё.

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое