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

Обнаружение уязвимостей в теории и на практике, или почему не существует идеального статического анализатора

Время на прочтение7 мин
Количество просмотров11K
Всего голосов 36: ↑35 и ↓1+34
Комментарии13

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

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

Их сложно обнаружить

Что-то PVS-Studio в каждом своем отчете пестрит обнаружениями use-after-free и подобных, включая null pointer dereference. Может, это и непросто, но по крайней мере, выполнимо, подчас довольно легко (если вместо !=null стояло ==null).

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

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

  • ошибки валидирования,
  • ошибки утечки информации,
  • ошибки аутентификации.
Интересно, почему обычно в этой и аналогичных статьях не говорят про опечатки и Copy-Paste. У нас их есть… :) См. в таблице список диагностик, которые напрямую или косвенно выявляют опечатки и Copy-Paste. И да, опечатки могут являться дефектами безопасности.
Наверно потому, что это ортогональные вещи. Опечатки могут приводить к ошибкам проверки, но злоумышленников интересует именно ошибки проверки вне зависимости от причины их происхождения, а не опечатки как таковые.
Моё личное мнение, что граница между всеми этими вещами более размыта, чем хотят продемонстрировать. Возьмем, например, утечку памяти. С одной стороны, это просто ошибка. С другой, это ошибка, которая может привести к отказу в обслуживании. И ещё вопрос, как её классифицировать (валидация, утечки информации, аутентификация).

Или вот, например, уязвимость CVE-2012-2122 в MySQL, описанная в этой заметке. Значение типа int записали в char и потеряли значения старших бит. Можно сказать, что это ошибка валидации. Но, с другой стороны, это просто неаккуратность, которая при определённых условиях проявляет себя. Я плохо представляю, как искать такую ошибку с позиции философии «ошибка валидации». Вот проверка. Вроде работает. Как ошибку то найти? Зато понятно, как искать такую ошибку с точки зрения банального усечения данных.

Написал, пожалуй, путанно. Вот что я хотел сказать: я считаю, что это не ортогональные вещи. Невозможно заранее выделить, что является опечаткой/просто багом или уязвимостью. И всё равно злоумышленнику/специалисту по безопасности приходится работать со всеми подозрительными местами.
Эта статья — о уязвимостях, которые могут быть использованы злоумышленником, то есть нештатных ситуациях.
Ваш анализатор (imho) — больше о ошибках программиста, соответствии результата работы программы той задаче, которая ставилась при разработке, то есть процессу штатного выполнения.
Разумеется, это пересекающиеся множества.
Восприятие нашего инструмента (просто поиск ошибок) — это наша недоработка в плане презентации инструмента, а не реальное положение дел. Мы недавно это осознали и начали учиться позиционировать PVS-Studio и как SAST решение.

Оказалось, что почти каждой нашей диагностике соответствует тот или иной CWE ID. А раз найденная ошибка классифицируется согласно CWE, значит она потенциально может являться уязвимостью. Таким образом получается, что почти каждая диагностика, реализованная в PVS-Studio, способна выявлять уязвимости.
PVS-Studio — неплохой инструмент для решения тех задач, которые он умеет решать. Посыл статьи таков — поймите, какие задачи задачи вам надо решить в рамках статического анализа, возьмите именно те инструменты, которые эти задачи решают, остальные задачи могут быть решены вручную или как-то еще.
Это верное замечание. Спасибо.
Данная классификация приведена как пример и не является стандартом, полной или еще какой-то… Скорее это даже просто мое видение, как можно разделять уязвимости по классами.
Чем более разнородны языки программирования, тем больше разнородных составляющих в характеристике каждой вершины, а значит, внутреннее представление неэффективно по памяти.

Насколько неэффективно по памяти? Будет ли это иметь значение при текущих объемах оперативной памяти? Внутреннее представление — это только одна часть анализатора. Так что надо как минимум измерить память при поиске уязвимостей, недостатков и понять сколько памяти потребляется на этом этапе. А если реализовывать абстрактную интерпретацию, то вообще в экспоненту можно уйти как по памяти, так и по скорости.


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

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


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

Наша практика показывает, что неэффективность по памяти в случае «универсального внутреннего представления на все» критична для промышленных приложений, несмотря на то, что реализация качественная. Более того даже HP Fortify, который заявляет, что у него единое NST на все поддерживаемые языки, в реальности несколько его модернизирует под каждую группу языков.
Никто не говорит, что надо иметь свое внутреннее представление под каждый ЯП, но в любом случае это должна быть некоторая семейственность внутренних представлений, каждое из которых заточено под свою группу ЯП.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий