воскресенье, 9 января 2011 г.

злобный пост

чтение книжек про поиск эксплойтов всегда навевало на меня лютую злобу зевоту
Вот например давеча читаю я A Guide to Kernel Exploitation - конкретно вторую главу, где перечисляются паттерны уязвимостей и думаю, что с поисками описанного вполне способна справиться не особо большая стая дрессированных обезъян:
  • uninitialized pointers using, страница 24. Вполне можно положиться на compiler warning
  • nonvalidated pointers, страница 25 - аналогично, правда нужно добавить атрибут "этот указатель передан из user mode"
  • integer overflow, страница 30 - аналогично
  • double fetch, страница 34 - практически один в один п.2
  • reference counting overflow, страница 39 - тут уже нужна некоторая подсказка компилятору - если мы не возвращаем значение из этой ф-ции, то любая ветка code flow ниже до return должна уменьшить счетчик ссылок
И так далее - поиск процентов 80 описанных уязвимостей вполне можно возложить на какой-нть валидирующий анализатор кода, к которому банально дописывать атрибуты функций и аргументов + пополняемый набор правил валидации.
Причем конкретно для kernel code - он почти всегда написан на plain C, так что его синтаксический разбор и построение графов code flow & data flow вполне способен реализовать в качестве курсача обычный студент

И хер там - вместо этого мы имеем своры т.н. касперски экспертов, которые вместо составления формальных правил продолжают корчить из себя Спасателей Вселенных и Единственных и Неповторимых Носителей Эзотерического Знания. Вот характерный пример:
К сожалению, еще не создана такая полезная вещь, как всеобъемлющий справоч­ник по вопросам безопасности. Те из нас, кто работают в этой области, зачастую создавали свои собственные справочники, содержащие перечни возможных нападений и уязвимых мест, которые встречаются в коммерческих продуктах, описаны в научной литературе или придуманы нами самими. Подобные перечни огромны — пару лет на­зад я составил такой список из 759 нападений, но и он не был исчерпывающим
 Падумаешь, 759, хоть 666 тыщ мульонов - пока они не формализованы в виде правил, которые можно проверять автоматически - все это кармадрочерство шаманство и эзотерика

Дичайше негодую например

Update: ветка обсуждения непригодности oacr для многих описанных случаев на rsdn

6 комментариев:

  1. А ещё, уязвимости в драйверах это:

    1) Уязвимости в следствии ошибок проектирования. Эффективной методологии автоматического выявления в принципе невозможно разработать.

    2) Уязвимости при парсинге данных какого-либо формата. Эффективно выявляются только фаззингом.

    3) Уязвимости, связанные с не очевидными нюансами работы каких-либо системных механизмов, на которые полагается драйвер (см. про известные эпизоды с RtlQueryRegistryValues и ProbeForRead/Write). Эффективно выявляются только после первого прецедента.

    ОтветитьУдалить
  2. уязвимостей при парзинге вполне можно избежать обычным стат. анализом кода. См. например сорцы darwin - конкретно парзер machO - там на каждое действие минимум 2 проверки

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

    ОтветитьУдалить
  3. Btw, OACR который в состав последнего WDK включен пробовал уже? Он что-то действительно интересное в плане выявления дефектов при статическом анализе умеет?

    ОтветитьУдалить
  4. если под последним имеется в виду wdk7 - то да
    особо ничего полезного он не умеет находить

    ОтветитьУдалить
  5. OACR - очередное частное решение, призванное выявлять наиболее типичные ошибки в ужасном коде, писанном откровенно криворукими программерами. В таком коде оно, конечно, что-нибудь найдет. Но для более-менее аккуратного программиста, использующего вдобавок собственные средства верификации (хоть те же assert'ы), такие проверялки - что телеге пятое колесо.

    По уму, проверки надо встраивать в компилятор. Например, дать возможность навешивать на функции, константы/переменные, классы и прочие сущности различные атрибуты, и указывать правила, которым они должны соответствовать. Например, функции можно приписать атрибуты Paged=true/false, IRQL=n, Locked=true/false, указателю - атрибут Paged=true/false, переменной - ConcurrentAccess=true/false, и так далее.

    ОтветитьУдалить
  6. ровно использование атрибутов в компиляторе и было реквестировано в исходном посте:
    "нужна некоторая подсказка компилятору - если мы не возвращаем значение из этой ф-ции, то любая ветка code flow ниже до return должна уменьшить счетчик ссылок"

    ОтветитьУдалить