Тестирование и аудит безопасности. Вопрос
205 сообщений
#14 лет назад
Цитата ("frig"):Цитата ("MMM_Corp"):
e1it3, я почему еще спрашиваю - можно то и самому протестировать, но редко кто это делает. ИМХО если ты сам написал код, то тебе будет сложно его ломать и тестировать тоже. Так, поверхностное тестирование производится, но это не то о чем я говорю. Речь не о проверке работоспособности, а о полномасштабных тестах, чтобы можно было с уверенностью сказать, что вот этот код работает и он безопасен.
почему сложно ломать свой код? код должен отвечать определенным требованиям, минимизируем лапшу, всю логику выносим в блоки которые принимают входящие параметры и не зависят от других блоков, потом валидируем входящие данные. в остальных случаях используем "соглашения". для того чтобы тестировать себя нужно отойти от кода хотя бы на день и забыть всё что ты о нём знаешь - потом попытаться получить любое непредсказуемое поведение
16382 сообщения
#14 лет назад
Цитата ("e1it3"):почему сложно ломать свой код?
Потому, что ломать не строить - душа не болит

Цитата ("e1it3"):
код должен отвечать определенным требованиям
Да до фени что там за код. Есть два состояния - работает или не работает. Там в черном ящике может быть хоть brainfuck, но он тоже может либо работать, либо нет. Правильно работать или не правильно работать. Быть уязвимым или безопасным. Собственно задача состоит не в том, чтобы сделать код красивым и удобным на этапе тестирования, а чтобы сделать его надежным и безопасным.
205 сообщений
#14 лет назад
Цитата ("frig"):Собственно задача состоит не в том, чтобы сделать код красивым и удобным на этапе тестирования, а чтобы сделать его надежным и безопасным.
ну в это то и ошибка, либо код прозрачный и как следствие он безопасный или код похож на лапшу в которой скрывается куча "жуков"
3562 сообщения
#14 лет назад
Цитата ("e1it3"):ну в это то и ошибка, либо код прозрачный и как следствие он безопасный или код похож на лапшу в которой скрывается куча "жуков"Неужели вправду не различаете: (не)прозрачный - (не)безопасный?
Это, безусловно, разные характеристики. Да красивый код проще делать безопасным чем некрасивый, но прозрачность кода не есть необходимое и уж точно не достаточное условие для того что бы он был безопасным.
16382 сообщения
#14 лет назад
Цитата ("e1it3"):либо код прозрачный и как следствие он безопасный
Практически никак не связанные вещи. Код может быть красивущим, но тем не менее изобиловать дырами. И с другой стороны может быть хоть свалка, но все фильтроваться и никакие "жуки" не пролезут. Никак это между собой не связано. Красота кода - вопрос легкости его поддержки. А безопасным может быть и абсолютно непонятный код. Обсфуцированный код - не понятен и ужасен, но может быть безопасен.
SmartDesign опередил

205 сообщений
#14 лет назад
Цитата ("SmartDesign"):Неужели вправду не различаете: (не)прозрачный - (не)безопасный?
Это, безусловно, разные характеристики. Да красивый код проще делать безопасным чем некрасивый, но прозрачность кода не есть необходимое и уж точно не достаточное условие для того что бы он был безопасным.
прозрачность не подразумевает красоту, а подразумевает легкость определения состояния внутри кода
Цитата ("frig"):
Практически никак не связанные вещи. Код может быть красивущим, но тем не менее изобиловать дырами. И с другой стороны может быть хоть свалка, но все фильтроваться и никакие "жуки" не пролезут. Никак это между собой не связано. Красота кода - вопрос легкости его поддержки. А безопасным может быть и абсолютно непонятный код. Обсфуцированный код - не понятен и ужасен, но может быть безопасен.
если ставить изначальное условие что красивый код пишем без намека на фильтрацию данных, то конечно да, но при более равных условиях мы уже получаем совсем другие результаты: каким образом тестировать "фаршкод" - да только одним - расставляя по всему коду дебаг
16382 сообщения
#14 лет назад
Цитата ("e1it3"):если ставить изначальное условие что красивый код пишем без намека на фильтрацию данных, то конечно да, но при более равных условиях мы уже получаем совсем другие результаты
Результаты будут равны. Безопасность и красота зависят от разных вещей. Точно также как безопасность и красота автомобиля - если водитель не пристегнут то плевать красивый автомобиль или нет, при серьезном столкновении он погибнет. А там хоть стразики, хоть что угодно.
3562 сообщения
#14 лет назад
2 e1it3: "при прочих равных проще сделать безопасным" сильно отличается от "как следствие безопасный". не находите?
702 сообщения
#14 лет назад
Выскажу и я свое скромное мнение, поскольку данный вопрос входит у меня в повседневные.Позволю себе не стесняться в выражениях. Оправдать меня может в этом смысле только то,
что я в последнее время редко захожу на форум - надо же наверстывать упущенное.
Прошу не принимать близко к сердцу некоторые резкие замечания, а также склонность к
"яканью", которая у меня с детства.
Про качество кода, который пишется программистом.
Качество работы программиста во многом зависит не только от навыков в предметной
области, но и от общей культуры кодирования, от самодисциплины и методологий,
которые он применяет, а также от умения пользоваться разнообразными инструментальными
средствами и библиотеками. Приводить их здесь, а тем более обсуждать, не имеет
смысла ввиду обширности данной темы - она практически неисчерпаема.
Каждый подход сам по себе "весит" очень немного, но в сочетании вместе они формируют
площадку для комфортной работы и сопровождения.
И еще, лично мое мнение. Некоторым просто не дано работать программистами и вообще
заниматься точными науками, хотя бы в силу врожденных черт характера - невнимательности,
нелюбви к мелочам и т.п. Иными словами, если человек из года в год пишет плохой код,
то ему не место в IT.
Про тестирование.
К качеству этого процесса, когда он выполняется "на стороне", отношение двоякое.
С одной стороны - выделенный профессионал или даже группа профессионалов.
С другой - есть большой диапазон ошибок, которые практически невозможно даже
обнаружить, не говоря уже о точной диагностике причин.
Возьмем пример - многопоточная программа с нетривиальной логикой и изобилием
самописных алгоритмов синхронизации, lock-free-очередей и тому подобного.
Как наиболее достоверно убедиться в том, что программа работает корректно и в ней
отсутствуют скрытые ошибки ? Качественная ревизия кода возможна только человеком
из числа разработчиков. Тестирование тоже ничего не дает - программа может сто раз
работать, а на сто первый упасть на глазах руководства, прямо во время презентации.
При этом проходятся все use-cases и во всем остальном демонстрируется полная
работоспособность. В продолжение - что делать, когда программа упала ? Логов нет,
получаем скупое "access violation" или вообще висим, при следующем запуске все
опять работает как ни в чем не бывало.
Предположим, подозрения падают на один из компонентов. Нужно вычленить его из кода и
протестировать изолировано, на большом количестве потоков и входных данных.
Хорошо, если это возможно. А если компонента как такового нету и логика работы данной
подсистемы разбросана по нескольким десяткам функций ?
Отсюда можно вывести несколько правил.
1. Поддержка тестирования закладывается в программе с первых строк.
Юнит-тесты, а также сценарии стресс-тестирования, пишутся в первую очередь и
интегрируются в рабочий цикл. В TDD тесты пишутся до кода - мне кажется, что
вполне можно отложить эту операцию на чуть более поздний срок.
Самое главное то, что разрабатывая очередной класс и попутно думая о его
предстоящем тестировании, улучшается структура кода. Формируется, так сказать,
нужная гранулярность. Компоненты перестают быть похожими на монстров (слишком
толстые) или моллюсков (слишком мелкие), а сами "выбирают" нужный размер.
Написанные тесты немедленно становятся частью проекта и частью его системы сборки.
В некоторых IDE можно запускать тесты только для измененных частей кода - это
полезно, когда проект большой и полное его тестирование занимает несколько часов.
Но даже в этом случае полные тестовые комплекты (suites) должны запускаться регулярно.
У меня, например, тесты запускаются на билд-сервере, сразу после сборки, затем
генерируется отчет, который можно посмотреть через веб-панель.
2. Тестирование GUI, а также функциональные и стрессовые тесты, должны выполняться
собственными силами, желательно в автоматическом режиме.
Вот где помогают инструменты наподобие TestComplete и AutoIt, а также всевозможные
языки сценариев. Только если в данной области совсем нет навыков, можно передать
данную работу тестерам. Причины очевидны - разработчики лучше знают свой код и его
узкие места, знают чем можно пожертвовать. К тому же не везде организована настолько
качественная обратная связь между отделами разработки и тестирования, чтобы при каждом
новом изменении можно было увидеть эффект уже через несколько минут.
А инструменты автоматизации успешно справляются с этим, не требуя почти ничего взамен.
Разумеется, если мы пишем продукт уровня Office, AutoCAD или Visual Studio, нам
не обойтись без специальных подходов в этом вопросе, но это коснется и всех остальных
аспектов работы, а не только тестирования. Для небольших и средних продуктов
самостоятельное и автоматизированное тестирование вполне типично.
В одном из моих проектов для тестовых целей был написан веб-сервер, работающий
локально и почти идентичный реальному. Потратив два дня на его написание, мы
позже сэкономили массу энергии по воспроизведению нескольких трудных багов и
смогли убедиться в том, что в новых версиях баг действительно закрыт.
3. Необходимо позаботиться о наиболее эффективной обратной связи.
Фактически, тестирование - это способ улучшения обратной связи и способ уменьшения
времени существования ошибки между моментом ее появления в программе и моментами
обнаружения и фиксации.
Тесты должны пролетать быстро, в идеале - за несколько секунд.
И запускаться они должны одной кнопкой.
Получение результата должно быть моментальным, без заглядывания в базу данных и т.п.
Очень рекомендую всякие уведомители, сидящие в трее, которые издают звуки сирены.
Еще один аспект обратной связи - отчет об ошибках.
Программу необходимо научить падать так, чтобы сохранять при этом логи, стек вызовов,
даже дамп памяти. При этом пользователь не должен быть обременен заполнением множества
форм. Хороший вариант - получить краткое описание ошибки и отправить отчет по
электронной почте, со скриншотами, штампом времени и параметрами системы.
Качественно написанные системы трассировки и крэш-репортов на самом деле почти не
требовательны к ресурсам и я уже долгое время практикую их включение даже в релизные
версии своих программ.
4. Проект должен поддерживать осмысленную нумерацию версий.
Это важнейший аспект, который часто недооценивается.
Все сборки продукта, которые так или иначе доходят до тестеров, конечных пользователей и
других клиентов, должны строго и по системе нумероваться, причем номера полезно хранить
внутри генерируемых логов и отчетов об ошибках. Так достигается гарантия, что возникающие
проблемы могут быть однозначно закреплены за соответствующими изменениями исходного кода.
Надеюсь, понимание того, что исходный код хранится в репозиторях SVN, Git, Perforce или
TFS, у читающих присутствует. Отсюда же полезное правило - в номере версии программы
должна содержаться информация о ревизии, соответствующей коду, из которого эта программа
была собрана. Например, я предпочитаю такую схему: Major.Minor.Build.Revision.
Major и Minor - номера, собственно, продукта, Build - инкрементный счетчик, увеличивающийся
на единицу после каждой сборки билд-сервером, Revision - номер соответствующей ревизии в
хранилище кода, из которой была собрана программа.
Когда вы получаете отчет об ошибке, случившейся в версии A.B.C.D, вы сразу заглядываете в
хранилище кода и смотрите в хронологическом порядке несколько последних изменений,
внесенных до ревизии D. Этот подход упрощает отслеживание некоторых категорий ошибок.
5. Необходимо позаботиться о тестовой площадке и испытаниях в реальных условиях.
Многие слышали такой термин - бета-версия. Однако помимо альфы, беты и
релиз-кандидатов, существуют еще несколько делений, отражающих поэтапную природу
введения продукта в эксплуатацию.
Конечно, нелепо выглядит HelloWorld 4.1.119.2237 RC 4 Service Pack 1.5a, но в больших
программах именно такой подход и практикуется.
Очень хорошо, когда часть работы по испытаниям в реальных условиях берут на себя
заказчики системы и просто будущие пользователи. Это процесс, взаимовыгодность которого
не нуждается в комментариях.
6. Надо побороть в себе лень или неприязнь и научиться пользоваться вспомогательными
инструментами и технологиями, которые предлагаются в данной сфере.
Эта фаза - моя любимая. Фактически, выполняется стресс-тестирование кода и его
стресс-анализ. Код программы прогоняется через разные компиляторы и анализаторы кода,
пересобирается с опциями динамических проверок, проблемы многопоточности выявляются
специальными инструментами вроде MS CHESS, Intel Thread Checker или Relacy Race Detector,
на вход программы подается огромное количество бессмысленных данных (фаззинг),
она запускается в среде с ограниченными ресурсами (Application Verifier), симулируются
сбои разного уровня, вплоть до отключения напряжения сети, для тестирования используются
разные редакции операционной системы, 32-битные и 64-битные.
Сам код, даже его релизные версии, может содержать массу проверок, как статических,
так и динамических, использовать разные утверждения для контроля корректной семантики
использования, постоянно проверять инварианты и всевозможные границы условий.
Полезно, по крайней мере иногда, иметь возможность включить такие "регуляторы" на
максимум и посмотреть эффект.
Про аудит безопасности.
Безопасность ПО относится к архитектуре проекта в гораздо большей степени.
Другими словами, если тестирование способно помочь выявить и пофиксить баги,
то аудит безопасности является способом вынести вердикт всей системе, причем
часто такой вердикт, который обжалованию не подлежит.
Как бы вы отнеслись к идее банковского или другого веб-сервиса оплаты, построенном
на незашифрованных каналах связи ? Скорее всего, резко отрицательно.
В отличие от тестирования, без услуг специалиста по компьютерной безопасности
иногда невозможно обойтись, и здесь знание им предметной области решает.
Лично у меня здесь как раз отрицательный опыт - я со временем нахожу "дыры" в
своих программах и приходится рапортовать об этом заказчикам и выпускать
обновления. А ведь данную работу можно было проделать однократно и забыть.
На этом все.
Абсолютно без претензий на полноту или авторитетность.
16382 сообщения
#14 лет назад
okman, спасибо за пост. Весьма ценно!У нас конечно попроще чуток - и окружение более менее стабильно и скрытых проблем не так много. Веб в этом отношении прозрачнее.
205 сообщений
#14 лет назад
Цитата ("SmartDesign"):2 e1it3: "при прочих равных проще сделать безопасным" сильно отличается от "как следствие безопасный". не находите?
вы цитируете себя, а не меня и вижу что суть не видете
