О статическом анализе кода в теории и на практике

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

О статическом анализе кода в теории и на практике

Кратко о статическом анализе кода

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

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

Инструменты и технологии для статического анализа кода

Одним из современных статических анализаторов является инструмент PVS-Studio. Этот инструмент позволяет выявлять ошибки и потенциальные уязвимости в исходном коде программ, написанных на языках С, C++, C# и Java. Работает в 64-битных системах на Windows, Linux и macOS и может анализировать код, предназначенный для 32-битных, 64-битных и встраиваемых ARM платформ. Кратко рассмотрим, какие технологии использует PVS-Studio при анализе исходного кода.

Анализ потока данных

Начнем с анализа потока данных. Он позволяет вычислить возможные значения переменных в разных точках программы. Благодаря Data-Flow Analysis можно находить такие ошибки, как выход за границу массива, утечки памяти, разыменование нулевого указателя и т. д.

Аннотирование методов

Ручное и автоматическое аннотирование методов. Оно предоставляет больше информации об используемых методах, чем может быть получено путём анализа только их сигнатуры.

Сопоставление с шаблоном

Сопоставление с шаблоном. Анализатор, проверяя код, может находить заданные заранее паттерны, типичные для какой-либо ошибки. В простейшем варианте этот поиск похож на поиск ошибок с помощью регулярных выражений, однако всё обстоит несколько сложнее. Для поиска ошибок используется обход и анализ дерева разбора. Почему для этих задач неприемлемо использовать регулярные выражения, можно узнать из статьи «Статический анализ и регулярные выражения».

Символьное выполнение

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

Не зная ничего о значениях переменных A, B и C, анализатор PVS-Studio способен понять, что условие (A > C) всегда ложно, и сообщить об этом разработчику. Подробнее с этим и другими принципами, положенными в основу анализатора, можно познакомиться в статье «Технологии, используемые в анализаторе кода PVS-Studio для поиска ошибок и потенциальных уязвимостей».

Я знаю, о чем подумали некоторые читатели этой статьи. Это все, конечно, классно, но зачем нам статический анализ? Приведу пример из своей жизни. У меня был маленький пет-проект – светодиодные костюмы, которые светятся и моргают под музыку (при нажатии кнопки «плей» в программе на компьютере запускается таймер, который и отправляет на светодиоды значение RGB). Однажды, внеся очередные правки в код, я включила костюм и поняла, что он сходит с ума. Костюм хаотично моргал и светился теми цветами, которые я видеть вообще не ожидала, и больше напоминал кошмар эпилептика, чем светодиодную шмотку. На поиск ошибки у меня ушло, наверное, около часа, я перечитывала свой код немыслимое количество раз, а причина оказалась в банальной опечатке в одной цифре… мда.

К слову, ошибку, которую я допустила, успешно находит статический анализ.

Предупреждение PVS-Studio: V3013 It is odd that the body of ‘saveip6_Click’ function is fully equivalent to the body of ‘saveip7_Click’ function (5254, line 5260). MainWindow. xaml. cs 5254

Тут я методом копипасты писала код, сохраняющий ip-адрес контроллеров костюмов из текстбоксов. И, дабы быть честной, признаюсь, что цифра 6 тут из головы. Я не помню, в каком конкретно обработчике событий так неудачно накопипастила. Ну и не важно, самое главное – передать суть.

Однако у меня была довольно небольшая кодовая база и, следовательно, маленький объем всевозможных ошибок и опечаток. Цифры, взятые из книги Стива Макконнелла «Совершенный код», гласят, что с ростом размера проекта растёт и плотность ошибок.

Скриншот 1

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

Статический анализ кода на практике

Давайте теперь перейдём от теории к практике и на примере посмотрим, какие ошибки можно выявлять с помощью статического анализа кода. Для этого возьмём небольшой реальный открытый проект Extended WPF Toolkit и проверим его с помощью PVS-Studio.

Extended WPF Toolkit – это коллекция элементов управления и компонентов для WPF приложений. Проект включает в себя около 600 файлов исходного кода на языке C# и около 112 тысяч строк. Этот бесплатный набор инструментов имеет открытый исходный код и предоставляется в рамках лицензии Microsoft Public License. Также разработчики уже на платной основе предлагают воспользоваться Toolkit Plus Edition и Business Suite, в которых еще больше разнообразных компонентов и элементов управления, несколько тем под Metro и Windows 10 и многое другое.

Впрочем, все эти подробности нам не очень важны. Главное, что это обыкновенный типовой проект, написанный на языке C#. Давайте рассмотрим некоторые из ошибок, который в нём были найдены. Надеюсь, приведённых примеров будет достаточно для получения общего представления о технологии анализа кода. Более полное впечатление вы сможете составить самостоятельно, скачав и запустив анализатор на своих проектах. См. также «Как быстро посмотреть интересные предупреждения, которые выдает анализатор PVS-Studio для C и C++ кода?».

Примеры найденных ошибок

Предупреждение PVS-Studio: V3006 The object was created but it is not being used. The ‘throw’ keyword could be missing: throw new InvalidOperationException(FOO). DockingManager. cs 1129

Это предупреждение анализатора сообщает о том, что был создан экземпляр класса InvalidOperationException, который в коде не используется. Видимо, программист хотел, чтобы при выполнении условия генерировалось исключение, но забыл написать оператор throw, который бы это исключение вызывал.

Предупреждение PVS-Studio: V3083 Unsafe invocation of event ‘PropertyChanged’, NullReferenceException is possible. Consider assigning event to a local variable before invoking it. CheckListsView. xaml. cs 124

Анализатор предупреждает о том, что был создан потенциально небезопасный вызов обработчика события. Проблема этого кода заключается в том, что одной проверки на null в этом случае недостаточно. В многопоточном приложении между проверкой на null и кодом в then-ветви оператора if может выполниться код в другом потоке, выполняющий отписку от данного события. Если это произойдет, и подписчиков у события не останется, то такой случай приведет к возникновению исключения NullReferenceException.

Для того, чтобы гарантированно произошло безошибочное выполнение вызова события, есть несколько способов переписать этот код. Я приведу один пример, а разработчики сами решат – воспользоваться моим способом, найти другой, и стоит ли вообще с этим кодом что-то делать.

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

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

Предупреждение PVS-Studio: V3117 Constructor parameter ‘ignore’ is not used. AnimationRate. cs 59

Это предупреждение говорит о том, что параметр ignore не используется в этом коде. Судя по названию параметра, это ложное срабатывание и вскоре ‘ignore’ уберут из этого кода. Если это так, то предлагаю использовать атрибут ‘Obsolete’, который используется как раз в таких случаях.

Предупреждение PVS-Studio: V3114 IDisposable object ‘reader’ is not disposed before method returns. CSharpFormat. cs 211

Анализатор указывает на то, что объект reader класса StringReader реализует интерфейс ‘IDisposable’, но метод Dispose() для этого объекта в коде не был вызван. Тут, на самом деле, возникла двоякая ситуация. Класс StringReader и правда реализует данный интерфейс, но он его унаследовал от базового класса и никакими ресурсами он не владеет, поэтому вызывать Dispose() в этом случае не обязательно.

Анализатор обращает внимание на то, что в двух условиях подряд проверяется одно и то же значение на null. Возможно, проверка избыточна, но так же есть и вероятность, что второе условие должно выглядеть иначе. Сложилось впечатление, что этот код просто не дописан.

Предупреждение PVSStudio:

V3084 Anonymous function is used to unsubscribe from ‘HeaderDragDelta’ event. No handlers will be unsubscribed, as a separate delegate instance is created for each anonymous function declaration. ChildWindow. cs 355

V3084 Anonymous function is used to unsubscribe from ‘HeaderIconDoubleClicked’ event. No handlers will be unsubscribed, as a separate delegate instance is created for each anonymous function declaration. ChildWindow. cs 356

V3084 Anonymous function is used to unsubscribe from ‘CloseButtonClicked’ event. No handlers will be unsubscribed, as a separate delegate instance is created for each anonymous function declaration. ChildWindow. cs 357

В этом коде _windowControl отписывается от события, а потом подписывается обратно. Проблема кроется в том, каким образом происходят манипуляции с событиями при помощи лямбда-выражений. Дело в том, что каждое объявление анонимной функции приводит к созданию отдельного экземпляра делегата. Корректный вариант использования анонимных функций при подписке с дальнейшей отпиской на события представляет собой создание и использование переменной, в которую сохранен обработчик-лямбда, например, так:

Предупреждение PVS-Studio: V3013 It is odd that the body of ‘OnMaxScaleChanged’ function is fully equivalent to the body of ‘OnMinScaleChanged’ function (656, line 695). Zoombox. cs 656

В этом коде анализатор нашел две функции OnMinScaleChanged и OnMaxScaleChanged, реализованные идентичным образом. При этом в коде было создано свойство зависимости с именем MaxScaleProperty. Есть подозрения, что во втором случае код должен выглядеть так:

Подобные ошибки, найденные анализатором:

Предупреждение PVS-Studio: V3051 An excessive type cast. The object is already of the ‘Magnifier’ type. MagnifierManager. cs 62

Анализатор указывает на то, что программист привел объект к своему же типу. Данная проверка является избыточной. Это не является ошибкой и можно оставить ключевое слово var в объявлении magnifier, но нагляднее будет явно указать тип переменной.

Обычно после описания ошибки идет перечисление всех мест, где попадался подобный ошибочный код, но в этом случае выписать все предупреждения не получится. В коде попалось более 50 (!) подобных предупреждений анализатора (не считая того, что могло попасть на уровень Low, который я смотрела не так внимательно, как остальные), что на мой взгляд чересчур много.

Предупреждение PVS-Studio: V3116 Consider inspecting the ‘for’ operator. It’s possible that the loop will be executed incorrectly or won’t be executed at all. CollectionControl. cs 642

Код в цикле for не выполнится ни разу по следующим причинам: сначала программа очищает list, потом сравнивает размер sourceList и list (генерируя исключение, если количество элементов в sourceList больше чем в пустом list), а далее пытается заполнить список list значениями из sourceList через цикл.

Предупреждение PVS-Studio: V3020 An unconditional ‘break’ within a loop. LayoutRoot. cs 542

Вне зависимости от значения singleChild. ChildrenCount, из-за оператора break выполняется ровно одна итерация цикла foreach. Да и вообще код очень странный, непонятно, стоит ли это расценивать как ошибку, вдруг это так и было задумано…

Заключение

На примере проекта Extended WPF Toolkit мы убедились в значимости статического анализа при создании программного продукта. WPF Toolkit представляет собой совсем небольшой проект, однако на 112 тысяч строк кода попалось довольно много однотипных ошибок, вроде идентично реализованных методов, приведения объектов к своему же типу и т. д. Все эти ошибки легко находятся при помощи статического анализатора кода PVS-Studio, которым можно воспользоваться, скачав пробную версию по ссылке. Если ввести промокод #infocomp в поле «Сообщение», то можно получить лицензию на один месяц вместо 7 дней.

AppChecker — инструмент статического анализа

В настоящее время информационные технологии проникли практически во все сферы ведения бизнеса. Для решения бизнес-задач создаются крупные, распределенные, постоянно модифицируемые информационные системы с тенденцией к усложнению. Они могут иметь в своем составе как готовые решения, так и внешние IT-сервисы (SaaS), собственные и заказные разработки, бесплатные продукты с открытым исходным кодом (open source). Проблемы в их работе приводят к нарушению информационной безопасности, а как следствие, к финансовым и репутационным потерям бизнеса. По данным исследования [9], последние четыре года финансовые потери бизнеса растут из-за кибератак. Повышение сложности используемых программных комплексов, их включение в контур систем управления государством и производством промышленной продукции требуют постоянного совершенствования методов тестирования, испытаний и контроля программного обеспечения.

Большинство методов анализа ПО, применяемого в аудите безопасности программных систем, можно разделить на две группы (рис. 1) — динамические методы (функциональное тестирование) и статические методы (структурное тестирование).

классификация видов анализа программ

Рис. 1. Примерная классификация видов анализа программ (цветом выделены те виды анализа, о которых говорится в данной статье)

Динамический анализ представляет собой совокупность всех методов анализа программного обеспечения, реализуемых с помощью программ на реальном или виртуальном процессоре. Такие способы наиболее востребованы при исследовании программ методом «черного ящика» (black box), когда имеется доступ лишь к внешним интерфейсам программного обеспечения без учета их структуры, внутренних интерфейсов и состояния [5]. Этот подход не всегда эффективен при поиске ошибок, связанных с комбинациями редко используемых входных данных, а также при выявлении скрытого программного функционала (программных закладок), внесенного туда преднамеренно.

Для своей работы статический анализ не требует реализации програм­много кода и допускает полную или частичную автоматизацию процесса, но предполагает доступ не только к загрузочным и объектным модулям, но и к исходным текстам программной системы, к информации, связанной со средой компиляции и выполнением программных компонентов [3–5].

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

Методы статического анализа кода

Статический анализ исходных текстов программного обеспечения тесно связан с принципами работы компиляторов. Многие подходы такого анализа основаны на некоторых элементах компиляции, в частности, промежуточное представление исходных текстов в статических анализаторах эволюционирует совместно с развитием теории компиляторов. Современные методы анализа в целях унификации алгоритмов используют различные модели представления кода, например лексический разбор, синтаксическое дерево, дерево Канторовича, графы потока данных и управления и т. д. [1].

Подход, получивший название сигнатурного анализа, подразумевает поиск дефектов в программном коде путем сопоставления фрагментов кода с образцами из базы данных шаблонов (сигнатур) дефектов безопасности. В зависимости от технологии, применяемой при сопоставлении фрагмента кода и шаблона, а также от промежуточного представления, могут использоваться как обычные алгоритмы поиска подстроки в строке, так и регулярные выражения, специальные языки запросов по структурированной информации, в частности XQuery для XML, или специально разработанные для этой задачи способы сопоставления. В [2] приведены примеры правил формирования сигнатур ошибок, соответствующих стандарту CWE. Признакам потенциально опасных конструкций в программных системах и методам оценки их безопасности посвящены статьи 6, 7].

Самый простой способ поиска потенциально опасных конструкций — применение регулярных выражений. Этот вариант достаточно прост в реализации (легко добавляются новые шаблоны уязвимостей), однако имеет несколько критических недостатков. В первую очередь к ним относится невозможность создать шаблоны для сложных дефектов, причем даже для простых дефектов кода регулярное выражение может занимать очень много места, а также очень низкая скорость поиска.

Более эффективным считается построение промежуточного представления кода и его анализ. Именно такой способ используется почти во всех современных анализаторах кода. Общее представление структуры статического анализатора показано на рис. 2.

Рис. 2. Структура статического анализатора

На начальном этапе решение задачи анализа исходного кода напоминает действия компилятора либо интерпретатора (в случае динамического языка). Исходные тексты разбиваются на лексемы, на основании которых впоследствии строится абстрактное синтаксическое дерево (Abstract syntax tree — AST) и в дальнейшем семантический граф (Abstract semantic graph — ASG). Далее AST и ASG анализируются механизмом, подобным поиску регулярных выражений в тексте, либо используются скрипты для анализа. Помимо этого, анализ графов выполнения и потоков данных (Data Flow analysis) может дать полезную информацию.

Примеры дефектов кода

Самые распространенные виды дефектов кода — ошибки программирования и злонамеренно внесенный код. Следует заметить, что не всякая ошибка программирования приводит к возникновению уязвимости, а только те, в результате эксплуатации которых страдают защищенность, целостность и доступность данных. Злонамеренно внесенный код, как правило, позволяет получить несанкционированный доступ к системе, но бывают и другие типы дефектов, приводящие, например, к удаленному выполнению кода, сбору и отправке конфиденциальной информации либо к реализации несанкционированных действий при наступлении определенного момента времени (time bomb).

К наиболее известным и опасным уязвимостям нужно отнести уязвимости следующих видов:

Отсутствие проверки вводимых данных

Уязвимость появляется, если не производится проверка данных, поступивших из поля ручного ввода данных; от пользователя ожидается простая информация, например имя, email, текст короткого сообщения. Если при этом в поле ввода дописать код специально сформированной команды SQL или Javascript, то данный код будет выполнен. Например:

$stmt = prepare_query(«SELECT * FROM users WHERE username =?»);

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

Ошибки работы с памятью

Чаще всего встречаются ошибки, приводящие к переполнению буфера. Они, как правило, возникают в программах на языках C и C++. Если программа получает данные извне и копирует их во внутренний буфер без проверки размера копируемой области памяти, то при получении достаточно большого объема сведений происходит запись передаваемых данных на место адреса возврата и данных других процедур в области памяти стека. Эта ошибка может быть использована злоумышленником, который подставит нужное значение на место адреса возврата таким образом, чтобы в процессе возврата из подпрограммы переход осуществлялся вовнутрь той же перезаписанной области данных, где можно разместить вредоносный код. Пример уязвимого кода:

int main(int argc, char *argv[]) <

strcpy(buf, argv[1]);
// копирование

// без проверки длины

Пример безопасного кода:

int main(int argc, char *argv[]) <

strncpy(buf, argv[1], sizeof(buf));

// копируется не больше

Ошибки реализации

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

Вредоносный код

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

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

Эффективность статического анализа

Сегодня использование статических анализаторов становится объективной потребностью для обеспечения защищенности современных программных систем с высоким уровнем доверия. Введение новых стандартов разработки безопасного ПО подтверждает необходимость эффективных инструментов, поддерживающих качество программного кода.

Использование AppСhecker [8] позволяет существенно упростить и сократить затраты на ревизию кода при разработке программ, а также повысить качество кода и сократить количество ошибок и уязвимостей еще на этапе проектирования, что также позитивно скажется на затратах на доработку и поддержку выпускаемого ПО.

Помимо основного функционала в любом программном обеспечении, взаимодействующем с пользователем, очень важно удобство его применения. Удобный и понятный интерфейс (рис. 3), интеграция в процесс разработки, простота установки, обновления и поддержки становятся важными характеристиками анализаторов кода. Тем не менее сделать анализатор полностью автоматическим, действующим по «нажатию одной кнопки», невозможно.

AppChecker

Рис. 3. Общий вид рабочего экрана AppChecker

Как уже упоминалось, работа анализатора во многом близка работе компилятора. И для того чтобы провести качественный анализ, требуются те же действия, которые выполняет система сборки: проанализировать зависимости в проекте, распознать и «подключить» библиотечные функции и т. д., что может потребовать дополнительных настроек процесса анализа. В сравнении с другими статическими анализаторами, AppСhecker предоставляет пользователям бо? льшую гибкость в настройке: он понятен простым пользователям, а опытные разработчики смогут интегрировать его в процесс сборки любой сложности.

Важной составляющей безопасности кода является применение проверенных сторонних компонентов — библиотек или готовых программ с открытым исходным кодом. Их можно проверить, сообщая авторам о найденных уязвимостях и создавая базу уязвимостей open-source библиотек. Это особенно актуально для поддерживаемых анализатором AppСhecker интерпретируемых языков PHP, Javascript, в которых программы хранятся в виде исходных текстов.

Заключение

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

Статический анализ кода: что могут инструментальные средства?

При передаче кода заказчику или в эксплуатацию тестированию кода по требованиям информационной безопасности не уделяется должного внимания. При этом квалификация злоумышленников растет каждый день, киберпреступники становятся опытнее и применяют новейшие технологии атак и взломов программного обеспечения. По данным института Ponemon, ущерб от киберпреступности за 2012–2014 годы вырос на 30%.

Современные системы состоят из множества компонент, между которыми очень сложные и непрозрачные связи. Эти связи достаточно трудно держать в поле зрения, если не используются специальные инструментальные средства (ИС), позволяющие визуализировать потоки данных, а также переход управления от компоненты к компоненте во время выполнения программы. Большинство популярных среди злоумышленников уязвимостей прячутся именно на стыках разных компонент.

Другие статьи автора

Статьи по теме

Поделиться

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

Инструментальные средства анализа кода

Сегодня ИТ-индустрия предлагает большое разнообразие инструментальных средств, без которых разработка программного кода невозможна. Также в современном мире сложно просто эксплуатировать программные продукты, закупленные у разных производителей. Ввод в эксплуатацию требует предварительной настройки ПО, обучения персонала его использованию, а требования к обеспечению ИБ диктуют необходимость защищать среду эксплуатации программного обеспечения посредством выстраивания так называемой защиты периметра.

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

Аналогичная ситуация имеет место и с анализом кода по требованиям ИБ. В настоящее время на рынке представлено много инструментальных средств – как коммерческих, так и свободно распространяемых. Большинство из них можно применять как в процессе разработки ПО для повышения надежности кода, так и для аудита уже готовых программных систем по требованиям информационной безопасности. Обычно такие системы используют при содействии экспертов в области ИБ, причем не в автоматическом режиме, так как задача обнаружения уязвимостей в коде очень сложна и ее качественное выполнение в других условиях невозможно.

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

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

Рис. 1. Магический квадрант Гартнера – производители решений для тестирования ПО на соответствие требованиям ИБ

В целом для инструментальных средств статического анализа кода характерны:

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

Помимо этого, инструментальные средства анализа кода должны анализировать программный код по внутреннему представлению, позволяющему учитывать особенности выполнения программы. Уязвимости, в отличие от недокументированных возможностей (НДВ), являются побочными эффектами выполнения кода, отвечающего за реализацию функционала системы. 90% современных уязвимостей, которые успешно эксплуатируются злоумышленниками, не идентифицируются посредством анализа только текста программы. Однако следует отметить, что обнаружение НДВ возможно посредством анализа только исходных текстов программы с применением библиотеки шаблонов, основанной на регулярных выражениях.

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

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

Пользовательский интерфейс также крайне важен: без качественной визуализации, обобщения и компактного представления информации никакой, даже самый полный, анализ не будет приносить должного результата. Люди – аналитики, разработчики, контролеры качества разработки кода – просто не смогут воспринять полученную информацию.

HP Fortify

Компания HP предлагает несколько продуктов для тестирования ПО на соответствие требованиям ИБ:

HP Fortify SCA дает хорошее качество сканирования. На наш взгляд, это лучшее сканирование по сочетанию «время работы/количество ложных срабатываний и пропущенных ошибок». В общей сложности это инструментальное средство было протестировано более чем на 15 тыс. CLOC (Count Lines of Code) различного кода, реализованного на разных языках. Количество пропущенных ошибок приближается к нулю, те же, которые есть, в настоящее время просто нельзя идентифицировать автоматически. Для повышения точности сканирования, то есть уменьшения количества ложных срабатываний, можно модифицировать набор предоставляемых правил. Сделать это просто, так как интерфейс ИС удобен, а язык правил доступен.

IBM AppScan

Линейка решений от компании IBM для аудита ПО на соответствие требованиям информационной безопасности состоит из следующих продуктов:

В состав AppScan Source входят инструменты для поиска и анализа уязвимостей в исходном коде (Source for Analysis), автоматизации процесса разработки (Source for Automation) и интеграции со средами разработки, такими как Visual Studio и Eclipse (Source for Development). Также в решение входит база знаний об уязвимостях и способах их устранения (Source Security Knowledgebase) и средство для централизованного обмена информацией об уязвимостях (Source Enterprise Server). Подробно рассмотрим AppScan Source for Analysis, а также перечислим основные понятия, используемые при анализе кода в рамках AppScan.

Данные, которые использует AppScan, организованы следующим образом:

Выявленные уязвимости могут быть классифицированы по следующим признакам:

Не все результаты поиска являются уязвимостями. AppScan предлагает следующий метод их классификации:

С целью обеспечения полной безопасности приложения нужно проводить дополнительные исследования для отнесения исключений либо к уязвимостям, либо к ложным срабатываниям, причём для обработки исключений типа II, как правило, требуется больше усилий. В дальнейшем для краткости мы будем называть результаты сканирования AppScan «уязвимостями», понимая под этим собственно уязвимости и исключения I и II типов.

Статический анализ IBM AppScan дает нормальное качество, однако складывается впечатление, что база правил здесь несколько более скудная, нежели у HP Fortify. Некоторые уязвимости ищутся по «старым» шаблонам. По соотношению «скорость сканирования/количество ложных срабатываний и пропущенных ошибок» ИС сильно уступает HP Fortify: количество ложных срабатываний меньше, но больше пропущенных уязвимостей. Как мы уже отмечали выше, ложные срабатывания при отсутствии пропусков ошибок лучше, нежели пропущенные ошибки с минимальным количеством ложных срабатываний.

Positive Technologies Application Inspector

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

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

ИС позиционируется как средство в помощь команде контроля качества разработки и информационной безопасности, а не разработчиков. Возможность интеграции со средами разработки и другими системами управления проектом отсутствует. Помимо этого, в настоящее время Application Inspector предоставляет статический анализ только для интерпретируемых языков, однако производитель говорит о том, что поддержка компилируемых языков также будет присутствовать.

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

Veracode

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

В то же время производитель анонсирует возможность выполнения статического анализа бинарного кода. Но при его загрузке на сервер необходимо предоставить информацию для отладки в виде так называемой Debug-сборки и со всеми сторонними библиотеками, которые подключаются к проекту на этапе динамической сборки. На практике же сторонний разработчик предоставляет систему в виде Release-, а не Debug-сборки: во-первых, декомпиляция приложения по Debug-версии значительно проще, чем по Release-версии, во-вторых, Debug-версия занимает значительно больше места и имеет сравнительно низкую производительность. К тому же если можно собрать сборку в виде Debug-версии, то исходные коды обычно тоже доступны.

На наш взгляд, возможность выполнения бинарного анализа при таком ограничении следует рассматривать как маркетинговое заявление, а не как особенность продукта, которая выгодно отличает его от других. Также следует отметить, что выполнение статического анализа кода удаленно предоставляет и компания HP.

Checkmarx

Еще одно инструментальное средство анализа кода, которое пытается завоевать рынок. Продукт показывает достойные результаты сканирования, однако складывается впечатление, что его база уязвимостей менее полная, чем у конкурентов, в частности, у HP Fortify. Мы проводили сравнение Checkmarx с HP Fortify SCA в 5 независимых проектах. Время работы средств было сопоставимым, однако количество выявленных действительных уязвимостей у HP Fortify оказалось значительно больше. Это свидетельствует о том, что Checkmarx пропускает уязвимости, которые можно идентифицировать автоматически.

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

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

InfoWatch APPERCUT

Отдельно стоит отметить еще одно ИС, которое позиционируется как инструментальное средство в помощь разработчикам и специалистам в области ИБ, – InfoWatch APPERCUT. Мы намеренно не называем его инструментальным средством статического анализа кода. Обычно под этим подразумевают ИС, которые анализируют особенности выполнения программы, моделируют преобразование данных в процессе ее работы. Именно на основании информации о преобразовании данных в процессе выполнения программы строятся заключения о наличии или отсутствии альтернативных сценариев эксплуатации ПО, которые могут использовать злоумышленники.

ИС APPERCUT выполняет анализ по текстовому представлению программы, при этом никакого анализа преобразования данных в процессе выполнения программы нет. Анализ строится на применении набора шаблонов языковых конструкций, которые потенциально неправильно использовать при кодировании.

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

Производитель заявляет, что у него большая библиотека шаблонов, и они позволяют находить большое количество уязвимостей и недокументированных возможностей. Следует отметить, что большинство ошибок и уязвимостей, которые можно идентифицировать посредством применения к программе лексического анализатора, выявляются средами разработки, так как при компиляции и трансляции в bite-code выполняется лексический анализ. Разработчики добавляют правила для поиска уязвимостей и ошибок на этапе компиляции и трансляции в bite-code. Выполнять более полную проверку на этой стадии среда разработки не может, так как это занимает много времени.

Эксперименты показали, что все уязвимости, которые находит инструмент APPERCUT для программ C/C++, обнаруживаются MVS (Microsoft Visual Studio) 2012 при включении опции полной проверки. Все уязвимости, которые находит APPERCUT для Java-программ, выявляет среда разработки Eclipse c плагином Find Bugs. Eclipse и Find Bugs – это свободно распространяемое программное обеспечение.

Возможно, данное ИС можно использовать в качестве продвинутого анализатора исходного кода с целью поиска недокументированных возможностей, закладок и проверки соблюдения определенных стандартов программирования, которые могут быть приняты в ИТ-компаниях. Однако можно с уверенностью сказать, что аналогичный функционал имеет любое инструментальное средство статического анализа кода, которое предоставляет интерфейс самостоятельного редактирования правил

Экспертная проверка кода по требованиям ИБ

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

Тогда компания будет иметь полную информацию о том коде, который собирается эксплуатировать, следовательно, она сможет принять правильное решение о том, как управлять ситуацией.

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

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

Понимание компанией итогов выполнения экспертного аудита кода зависит от представления этого результата в виде отчетов. Требования к отчетам разные:

Эксплуатация ПО в настоящее время должна выполняться под контролем службы информационной безопасности, для того чтобы бизнес мог управлять рисками. Аудирование ПО должны осуществлять исключительно ИБ-специалисты, так как найденные ошибки, которые на самом деле не являются критичными для эксплуатации, будут отвлекать программистов. Цена даже одной пропущенной ошибки в коде, которая будет успешно использована злоумышленником, может быть очень высокой.

Источники:

https://info-comp. ru/static-code-analysis

https://controlengrussia. com/programmnye-sredstva/bezopasnost-programmnye-sredstva/appchecker/

https://www. jetinfo. ru/staticheskij-analiz-koda-chto-mogut-instrumentalnye-sredstva/

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: