Как стать автором
Поиск
Написать публикацию
Обновить

Поймай уязвимость своими руками: пользовательские аннотации C# кода

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров2.6K
Всего голосов 5: ↑5 и ↓0+8
Комментарии14

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

Представим себе автора библиотеки, который публикует её в nuget пакета.

Как распространять такие аннотации?

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

Тем не менее, если пользователь библиотеки применяет PVS-Studio для анализа, он может самостоятельно разметить необходимые методы, конструкторы и свойства библиотеки.

Рацпредложение.

В C# есть возможность помечать методы и др. объекты атрибутами. Вы не думали над возможностью сделать аннотации с помощью атрибутов?

При этом, во-первых, уменьшится объем писанины, так как имя класса, метода и т.д. будет ясно из контекста, а, во-вторых, уменьшится вероятность ошибок при подготовке к повторной проверке: например, при переименовании метода его аннотация а птрибуте точно не потеряется, а в JSON имя метода надо поправлять отдельно. Недостаток, правда тоже есть: в коде появляется в зависимость от сборки с классами метаданных, которые совершенно не нужны в готовом продукте.

У нас были подобные мысли, но мы столкнулись с рядом трудностей и в итоге остановились на аннотациях в формате JSON. Кроме того, для C++ части PVS-Studio аннотации уже реализованы в формате JSON, и мы решили сохранить некоторое единообразие.

Не совсем понял из статьи зачем мне самому описывать аннотациями узкие/слабые/тонкие места, когда их можно закрыть от потенциальных уязвимостей более правильным написанием кода?
Из примера понял, что разработчик по какой-то причине не хочет или не знает как применять параметризированные запросы к БД. Но тогда аннотирование сего кода - это лишняя работа, т.к. всё равно придётся переписывать чтобы убрать предупреждение PVS-Studio?

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

Что касается переписывания кода из-за срабатываний PVS-Studio, это вряд ли можно назвать лишней работой. Анализатор указывает на потенциальную проблему, которую необходимо либо устранить, либо подавить срабатывание, если проблема не актуальна для конкретного случая.

Из примеров статьи я понял только то, что разработчик знает, что у него неправильно написан код и пишет аннотации для проверки этого неправильного кода. Не кажется вам, что это звучит странно? Напишем изначально неправильный код (даже для примера) и напишем аннотации для проверки этого неправильного кода.
Может есть другие примеры?

Что касается переписывания кода из-за срабатываний PVS-Studio, это вряд ли можно назвать лишней работой.

Это понятно, иначе зачем бы нам нужны были бы анализаторы кода?..

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

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

Ещё раз уточню: смысл аннотаций не в том, чтобы добавлять их после обнаружения проблемы, а в том, чтобы обнаружить ошибку сразу, как только она будет допущена, потому что для соответствующего метода уже существует аннотация.

В статье не указано, что разработчик знает о том, что код написан неправильно. Допустим, код был размечен одним разработчиком, знающим об уязвимостях, после чего над проектом начал работать другой, который о них не знает. Он вполне мог написать код, аналогичный тому, что приведён в примере.

Рассмотрим другой случай: разработчик, знающий об уязвимостях, разметил методы, после чего какое-то время не работал над проектом. Вернувшись к проекту, он забывает, что какой-то метод возвращает внешние данные, требующие проверки. Если данные из этого метода попадут в приёмник заражённых данных, он получит предупреждение от PVS-Studio.

Ещё раз уточню: смысл аннотаций не в том, чтобы добавлять их после обнаружения проблемы, а в том, чтобы обнаружить ошибку сразу, как только она будет допущена, потому что для соответствующего метода уже существует аннотация.

Но аннотацию пишу я сам и я сам понимаю, что тут может быть проблема. Следовательно, я сам могу переделать код на этапе его написания, когда осознал что тут может быть ошибка.

В статье не указано, что разработчик знает о том, что код написан неправильно. Допустим, код был размечен одним разработчиком, знающим об уязвимостях, после чего над проектом начал работать другой, который о них не знает. Он вполне мог написать код, аналогичный тому, что приведён в примере.

Если разработчик не знает, что код написан неправильно - то как тогда он сделает аннотирование для PVS? Ведь даже в вашем синтетическом примере в аннотации явно указано что может быть SQL-инъекция. Следовательно его можно тут же исправить. Если этого сделать нельзя - то можно оставить комментарий к коду. Ибо комментарий к коду быстрее прочитается, чем оповещение PVS.

Повторюсь ещё раз. Мне из статьи не совсем понятно как применять аннотирование для PVS. То, что пример синтетический - это плохо. Лучше бы показали на реальном примере (как у вас на стойках на конференциях сделано: карточки с ошибками, попробуй их там найди).
Сама идея аннотирования узких мест - мне кажется странной или я не понял её смысла.

Давайте попробуем разобраться на другом примере. Представим ситуацию, в которой разработчик 'A' написал методы GetUserInput() и ExecuteCommand(string sqlComand).

Первый метод возвращает пользовательские данные, а второй выполняет SQL-команду. После написания к разработчику пришло осознание, что GetUserInput возвращает пользовательские данные (т. е. taint), а ExecuteCommand выполняет SQL-команду (т. е. если в качестве аргумента будут переданы непроверенные данные, может произойти что-то нехорошее). Именно в этот момент разработчик понимает, что нужно написать аннотации для этих методов. Первая аннотация будет содержать информацию о том, что метод возвращает taint-данные, а вторая о том, что при попадании в первый параметр тех самых taint-данных может возникнуть SQL-инъекция. Как мы можем заметить, аннотации были написаны в тот момент, когда вышеупомянутые методы даже не были использованы. Т. е. того самого "неправильно написанного" кода ещё нет.

Спустя некоторое время появляется разработчик 'B'. Он решил получить данные, используя метод GetUserInput, после чего без проверки передал эти данные в ExecuteCommand. Поступил он не очень хорошо, но перед тем, как залить только что написанный код он запустил анализ. В результате он получит предупреждение о том, что возможно возникновение SQL-инъекции.

На самом деле, разработчик 'B' может отлично знать, что такое SQL-инъекция, но всё-равно допустить ошибку. Например, он вызовет метод GetData для получения SQL-команды. Возвращаемое значение этого метода зависит от метода Foo1, а возвращаемое значение метода Foo1 зависит от Foo2, Foo2 зависит от Foo3, а вот уже Foo3 зависит от GetUserInput. Получится ситуация, что разработчик напрямую не использовал GetUserInput, но всё-равно получил taint-данные для SQL-команды. После чего передал эти данных в ExecuteCommand.
А что будет, если он проанализирует код? Он получит предупреждение о возможной SQL-инъекции

Т. е. того самого "неправильно написанного" кода ещё нет.

Нет, уже есть неправильно написанный код - так он содержит потенциальную угрозу. И нужно в таком случаен не аннотации писать, а переделывать его!
Разработчик А понял, до начала использования своего кода, что он "плохой" и не стал исправлять, а просто пометил что код плохой. Причём пометил в отдельном месте, а не в коде оставил отметку.

Можете другой пример привести? На этом примере мы что-то никак не можем прийти к согласию )))

Мне кажется, Вы не улавливаете суть анализа помеченных данных. По и отдельности процедуры-источники и процедуры-стоки чувствительных данных могут быть корректны. А при взаимодействии - нет.

Условно говоря, функция записи на диск не виновата, что с её помощью в файл записываете в открытом виде секретный пароль пользователя.

Taint-анализ (анализ помеченных данных, taint checking).

Спасибо! Этот вариант я понял.

Ещё раз уточню: смысл аннотаций не в том, чтобы добавлять их после обнаружения проблемы, а в том, чтобы обнаружить ошибку сразу, как только она будет допущена, потому что для соответствующего метода уже существует аннотация.

Но аннотацию пишу я сам и я сам понимаю, что тут может быть проблема. Следовательно, я сам могу переделать код на этапе его написания, когда осознал что тут может быть ошибка.

В статье не указано, что разработчик знает о том, что код написан неправильно. Допустим, код был размечен одним разработчиком, знающим об уязвимостях, после чего над проектом начал работать другой, который о них не знает. Он вполне мог написать код, аналогичный тому, что приведён в примере.

Если разработчик не знает, что код написан неправильно - то как тогда он сделает аннотирование для PVS? Ведь даже в вашем синтетическом примере в аннотации явно указано что может быть SQL-инъекция. Следовательно его можно тут же исправить. Если этого сделать нельзя - то можно оставить комментарий к коду. Ибо комментарий к коду быстрее прочитается, чем оповещение PVS.

Повторюсь ещё раз. Мне из статьи не совсем понятно как применять аннотирование для PVS. То, что пример синтетический - это плохо. Лучше бы показали на реальном примере (как у вас на стойках на конференциях сделано: карточки с ошибками, попробуй их там найди).
Сама идея аннотирования узких мест - мне кажется странной или я не понял её смысла.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий