Tl; dr; Сегодня мы представляем результаты оценки конвейера статического анализа ShiftLeft на тесте OWASP, где мы достигаем 100% истинных положительных результатов при 25% ложных срабатываний. С итоговым индексом Youden, равным 75%, это делает наш анализ лучшим в своем классе, превышая коммерческий средний показатель на 45% и являясь единственным коммерческим статическим продуктом, способным идентифицировать все включенные уязвимости [1]. Мы обнаруживаем, что ложные срабатывания являются результатом нашего решения переопределить коллекции и строки - это сознательный выбор дизайна, поскольку мы оставляем точную коллекцию и отслеживание строк нашему агенту времени выполнения. Успех нашего анализатора основан на двух основных принципах: упорная работа по объединению существующих подходов из академических кругов в механизм обработки потоков данных отраслевого уровня и новый подход к моделированию, извлечению и оценке информационных потоков высокого уровня. Эта работа является частью наших постоянных усилий по разработке технологии анализа кода нового поколения, поскольку программное обеспечение продолжает завоевывать одну отрасль за другой.

Поскольку объем написанного и развертываемого кода неуклонно увеличивается с каждым днем, растет и потребность в автоматизации обнаружения уязвимостей. Ранее существующие продукты безопасности используют методы как статического анализа программ (продукты «SAST»), так и динамического анализа программ (продукты «DAST / IAST»), и, поскольку оба подхода имеют свои сильные и слабые стороны, существует значительный интерес к способам их объединения. дополнять друг друга. Хотя статический анализ отлично подходит для всестороннего выявления уязвимостей, он обычно приводит к недопустимому количеству ложных срабатываний. С другой стороны, динамический анализ не позволяет достичь того же уровня охвата и приводит к высоким затратам времени выполнения, если он применяется для всего приложения. Тем не менее, он очень эффективен для проверки того, действительно ли уязвимость срабатывает. Ложноотрицательные результаты - это проблема динамического анализа, а не ложные срабатывания.

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

На пути к новому поколению продуктов статического анализа

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

Однако качество продукции SAST вызывает проблемы. Чтобы не дискредитировать работу тех, кто работал до нас, из теста OWASP очевидно, что существующие статические анализаторы оставляют место для улучшения как с точки зрения истинно положительных, так и ложных срабатываний. С максимальным индексом Youden-Index в 39% предстоит проделать большую работу, чтобы продвинуть статический анализ туда, где он должен быть. В ShiftLeft мы полны решимости сыграть ключевую роль в стремлении к новому поколению продуктов статического анализа. Следующее поколение статического анализа должно масштабироваться до большого объема кода, обрабатываемого в современных организациях, интегрироваться в новые жизненные циклы разработки программного обеспечения и сближать разработчиков и операторов. Хотя впереди нас ждет много работы, мы уже добились значительного прогресса за последние 1,5 года, о чем мы поговорим ниже.

Результаты теста OWASP

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

[…] OWASP Benchmark Project - это набор тестов Java, предназначенный для проверки скорости и точности инструментов обнаружения уязвимостей. Первоначальная версия предназначена для поддержки инструментов тестирования безопасности статического анализа (SAST). Будущий выпуск будет поддерживать инструменты тестирования безопасности динамического анализа (DAST), такие как «OWASP ZAP, и инструменты тестирования безопасности интерактивного анализа (IAST). […] »

Как отмечает Крис Висопал из Veracode, тест OWASP предоставляет сценарий для запуска всех тестовых случаев, а это означает, что задача достижения охвата, с которой сталкиваются чисто динамические подходы, не учитывается тестом [2]. Поэтому в этом тесте мы оцениваем только наш статический анализатор и оставляем компоненты времени выполнения вне игры. В целом мы достигли индекса Юдена 0,78. Однако в тесте OWASP общие баллы рассчитываются как средние по категориям, чтобы присвоить каждой категории одинаковый вес. Это спорно, так как это означает, что решения в категориях с меньшим количеством образцов более актуальны. С учетом этого правила наша оценка составляет 0,75.

OWASP Benchmark 1.2 и результаты оценки. P / N - количество положительных / отрицательных образцов, TP / FP - количество истинных / ложных положительных результатов, TN / FN - количество истинных / ложных отрицательных результатов, TPR и FPR - истинно положительные и ложные положительные результаты, и, наконец, , Y - индекс Юдена. Мы показываем результаты по категориям, результаты, усредненные по всем категориям, и результаты по всем выборкам.

В прямом сравнении с другими инструментами (см. Таблицу 2) ShiftLeft - единственный инструмент, который обеспечивает 100% охват, за ним следует FBwFindSecBugs, который достигает 97%, однако за счет 58% ложных срабатываний. Следующий лучший коммерческий инструмент достигает 33%.

Таблица 2: Результаты OWASP Benchmark для 9 статических анализаторов. Известно, что коммерческие инструменты SAST 01–06 включают Checkmarx CxSAST, HP Fortify, IBM AppScan Source, Coverity Code Advisor, Parasoft Jtest, SourceMeter и Veracode SAST.

Ингредиент №1: наш трекер потока данных

Рабочей лошадкой нашего анализа является современный трекер потока данных, к которому мы пришли, объединив многие методы, разработанные и применяемые в академических кругах для автоматического обнаружения уязвимостей за последнее десятилетие. Наш трекер потока данных является межпроцедурным, чувствительным к потоку, контекстно-зависимым, чувствительным к полю и работает с промежуточным представлением кода (см. Графы свойств семантического кода). Механизм выполняет оперативный анализ точек для определения узлов вызова и может извлекать выгоду из результатов постоянного распространения, сокращения графа потока управления и проходов анализа инфраструктуры. Проходы анализа фреймворка могут обрабатывать файлы конфигурации, если они есть. Механизм потока данных предоставляет настраиваемый набор эвристик, позволяющий сообщать о результатах в приемлемые сроки. Например, мы разрешаем ограничивать количество ветвей, рассматриваемых в сильно связанных компонентах, максимальную длину пути и общее количество шагов вычисления. Трекер потока данных кэширует, где это возможно, и компрометирует там, где это необходимо. Еще есть возможности для улучшения, но даже сегодня мы можем идентифицировать все соответствующие потоки данных в тесте OWASP менее чем за 10 минут на процессоре Intel Xeon E5–1650 v3 @ 3,50 ГГц.

Ингредиент # 2: информационные потоки высокого уровня

Информационные потоки высокого уровня - это второй ключевой ингредиент, который способствует точности нашего анализа. Идея проста: для языков программирования высокого уровня, таких как Java, недостаточно отслеживать отдельные потоки данных между API, чтобы понять поток информации высокого уровня. Вместо этого необходимо объединить информацию из нескольких низкоуровневых потоков. Позвольте мне проиллюстрировать это на примере. Рассмотрим поток, выделенный жирным шрифтом в листинге 1: HTTP-запрос передается обработчику сообщений, параметры хранения карты извлекаются с помощью метода getParameterMap, а параметр vector извлекается из этой карты с помощью метода get. . Затем параметр сохраняется в переменной param, экранируется с помощью htmlEscape, переименовывается в bar, используется при инициализации массива, и, наконец, этот массив передается методу printf. На более высоком уровне абстракции это поток HTTP-запроса в ответ HTTP-сервера, а точнее, в ответ «text / html». Единственный другой важный аспект потока состоит в том, что данные проходят через процедуру экранирования, превращая ее в образец неуязвимого кода.

Листинг 1: (Низкоуровневый) первичный поток от запроса сервлета к `printf`. Экранирование выполняется, чтобы избежать межсайтового скриптинга. Логическое назначение вызова `printf` неясно, если также не проанализирована инициализация.

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

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

Листинг 2: (Низкоуровневый) поток дескриптора, который предоставляет информацию об инициализации и конфигурации места назначения данных. В сочетании с первичным потоком данных и потоками дескрипторов для источника и всех преобразований мы получаем высокоуровневый информационный поток.

В нашем примере есть единственный релевантный поток дескрипторов, а именно поток, который инициализирует экземпляр PrintWriter, переданный методу printf. Глядя только на первичный поток данных, мы видим только то, что вызывается метод java.io.PrintWriter.printf. Принимая во внимание поток дескриптора, выделенный в листинге 2, мы видим, что PrintWriter инициализируется из HttpServletResponse, и, следовательно, данные будут записаны в ответ HTTP. Мы также видим, что данные будут возвращены как «text / html», поскольку метод setContentType вызывается для дескриптора как часть его инициализации.

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

ЗАКЛЮЧЕНИЕ отражено-xss = FLOW IO (http)

- ›ДАННЫЕ (НЕ зашифрованы, НЕ хешированы, НЕ экранированы, НЕ закодированы)

- ›IO (печать И http-html)

Это правило указывает, что поток данных от http к операции печати, известный как запись HTML в HTTP, является отраженной уязвимостью межсайтового скриптинга, если данные не зашифрованы, хешированы, экранированы или закодированы в пути.

Анализ ложных срабатываний

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

1. Перекрытие коллекций (вариант 1). В листинге ниже показан первый фрагмент. Карта заполняется испорченным (`param`) и незапятнанным значением (` «a_Value» `), а незапятнанное значение извлекается из карты (в` bar`). Мы перехватываем коллекции, что означает, что если части коллекции испорчены, мы предполагаем, что вся коллекция испорчена, что приводит к ложному срабатыванию при извлечении незапятнанной части коллекции в этом примере.

2. Переопределение коллекций (вариант 2). В этом коде незапятнанное значение («safe»), испорченное значение («param») и другое незапятнанное значение («moresafe» `) добавляются в список. Первое значение впоследствии удаляется из начала списка, и извлекается элемент списка с индексом 1, то есть считывается незапятнанное значение «moresafe». Опять же, мы перехватили сбор данных, что привело к ложному срабатыванию.

3. Отключенные ветви. Наконец, в листинге ниже показан последний из трех фрагментов, вызывающих ложные срабатывания. В этом фрагменте второй символ взят из строки «ABC». Если это константа, результатом всегда будет «B», и, следовательно, все ветви следующего оператора switch, кроме одной, недоступны. Эта проблема может быть решена путем моделирования семантики charAt, соответствующей заменой switchTarget и выполнения постоянного распространения и сокращения графа потока управления. Поскольку мы не моделируем charAt, мы получаем ложные срабатывания для этого фрагмента.

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

Заключение

Повышенная автоматизация имеет решающее значение при обнаружении уязвимостей для масштабирования большого объема кода, который необходимо защитить в современных отраслях. Способность статически идентифицировать уязвимости всесторонне, эффективно и с небольшим количеством ложных срабатываний является важным примитивом для достижения этой цели, и в ShiftLeft мы вкладываем значительные усилия и энергию в достижение этой цели. Сегодня мы рады продемонстрировать успехи в этой области, предоставив первый статический трекер потока данных, способный обнаруживать 100% уязвимостей в тесте OWASP с частотой ложных срабатываний 25%. Эта частота ложных срабатываний значительно ниже, чем у других статических анализаторов, и может быть полностью связана с перегрузкой коллекций и строк - проблемой, с которой мы справляемся с помощью анализа времени выполнения на практике.

Благодарности

Хотя многие люди в ShiftLeft сделали эти цифры возможными, я хотел бы особо выделить вклад Маркуса Лоттманна и Нико Шмидта. Спасибо за ваш тяжелый труд!

[1] https://rawgit.com/OWASP/Benchmark/master/scorecard/OWASP_Benchmark_Home.html (по состоянию на 12 сентября 2018 г.)
[2] https://www.veracode.com/blog / 2015/09 / серебряная пуля-ни-одна-технология