суббота, 15 октября 2011 г.

Забавный секурити баг на досуге


Принимал я тут как-то на досуге участие в тестировании одного веб-проекта.
Функциональное тестирование. Работа с системой требует авторизации, капчи на каждом шагу, сесии и все такое.
В одном из сценариев пользователи аттачат файлы. По логике бизнес-процесса , скорее всего это будут в том числе и приватные документы. При аплоаде много чего проверяется, в том числе и допустимый размер аттача как на клиентской стороне , так и на сервере.
В общем , " как учили ". На залитый аттач пользователь потом может всегда найти ссылку для скачивания. Ссылка располагается в private-части. Вроде все вроде бы ок, если бы не тот факт, что в ссылке есть параметр file_id, который меня и заинтересовал.
Путем перебора от 1 до "пока не надоест" мне удалось вытянуть все аттачи, которые были зарегистрированы в БД всеми пользователями этого проекта.. К счастью заказчика тестирования - пока еще тестовыми пользователями. полный приват, в общем :) О баге, конечно же доложено.
Название проекта, конечно же , не сообщаю :)

"А король то голый.." (с) :)

p.s. Надо будет антивирусом проверить все выкачанное, а то как бы на радостях самого себя не протроянить через какой-нибудь "документ"...:D
Всем удачи и побольше любопытства - без него в нашем деле никуда )

среда, 5 октября 2011 г.

Автотесты: почему важно "не делать лишних движений"

Несколько слов о дизайне автоматических тестов.
Точнее о вопросе избыточности проверок. Существует подход к разработке модульных (Unit) автоматических тестов, который можно описать так "Проверяем одно условие за один тест" (Verify one condition per test). Применение такой стратегии дает множество плюсов: при провале тестов можно максимально быстро выявить узкое место, и, как следствие, максимально быстро устранить проблему. Пусть тестов станет больше, но плюсы, как правило перевешивают.
При автоматизации более громоздких регрессионных функциональных тестов подобная стратегия также применима. Только в роли единицы проверки должны выступать уже не "условия" , а конкретный вариант поведения. При этом, все что лишнее, и не влияющее на данный конкретный вариант поведения должно быть безжалостно ампутировано. Лишними могут быть: некоторые инициализирующие параметры объектов, а также проверки , которые уже делались или будут делаться в тестах, специально для этого предназначенных. В общем, не надо делать лишних движений, у которых нет конкретных целей.
Вот пример из реальной практике, иллюстрирующий вышесказанное:

1. есть автоматический функциональный тест, проверяющий некий вариант поведения системы
2. в ходе его инициализации создается объект "клиент", у которого есть как обязательные так и необязательные параметры, причем данному тесту ни один из них не важен - важен факт наличия объекта "клиент" и все..
3. тестировщик, который создавал тест, то ли копипастом, то ли для разнообразия решил заполнить поле email , причем указал там строку с емейлом "не по RFC" (на момент написания теста проверке необязательного email внимания не уделялось)
4. тест долгое время работал, проверял нужные варианты, давал результат
5. в какой-то момент проверке полей данного объекта уделили внимание, и ужесточили ее, создав соответствующие автотесты на эту новую "функциональность"
6. старый же тест начал проваливаться, причем, не доходя до своей целевой проверки - проваливаться на этапе инициализации. Причина, думаю, ясна - строка "отбалды" в поле email.

Тест пришлось править, тратить время. Пусть не много времени ушло данный конкретный тест, но в принципе - это лишняя трата времени, лишнее отвлечение внимания на провал теста. Причина - "лишние движения" и никому ненужная "кучерявость" теста. Всему свое место - фантазии и творчеству, в том числе :)

Вывод: чуть больше осознанности может сэкономить чуть больше времени для чуть более полезных вещей :)

Анализ покрытия кода с помощью gcov+lcov





Сегодня наконец-то выделил время на то, чтобы наладить анализ покрытия кода. Пока только покрытие операторов и функций.
Тестируемое приложение написано на Си, ОС linux. Компиллятор gcc. Приложение должно быть собрано с флагами компиллятора : -ftest-coverage -fprofile-arcs.
Для анализа покрытия использовалась утилита gcov, которая помогает провести анализ того, какие строчки кода и сколько раз были задействованы в ходе выполнения приложения.
В результате выполнения приложения генерируются специальные файлы для каждого файла исходников , в которых и содержится собранная информация о покрытии. Дальше с помощью утилиты lcov полученные данные обрабатываются и генерируется , цветастый и веселый html-отчет . Я , как преимущественно визуалист, особенно был рад получившейся наглядности :) Даже в первом приближении мне стало понятно, что в плане автоматизации будут некоторые изменения :)
Упомянутые утилиты бесплатны, присутствуют в репозиториях всех популярных дистрибутивов linux, а также могут быть скачаны с sourceforge, например.
Итак, метод опробовал. Планирую проводить отдельный анализ покрытия для сеансов unit-тестирования и отдельно для сеансов автоматического регрессионного тестирования.
В более отдаленной перспективе постараюсь также наладить анализ покрытия путей выполнения и условий, а также освоить gcov в связке с gprof, для профилирования приложения.

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

лучше 1 раз увидеть, чем 100 раз предположить :)

UPD 05/10/2011
При анализе результатов ночного прогона обнаружил небольшой бонус - gcov умеет и условия анализировать (см. пример на картинке вверху статьи ) . Приятная неожиданность :)