DJ-Andrey-sXe Защита веб-приложений на Perl
40 правил
Вторая версия статьи (включает 18 пунктов из первой версии), обновлена: 5 июня 2012.Оригинал статьи: http://dj-andrey.ru/articles/perl-web-application-security
Сборник практических правил и советов с примерами и разъяснениями. Главным образом речь идет о языке Perl и сервере Apache, но многое из сказанного справедливо для других подобных средств разработки.
Приведённые примеры кода не претендуют на универсальность и законченность, однако, они все проверены и работают на свежих версиях Perl. Почти все пункты уже применялись в реальных скриптах, и я чуть ли не каждую неделю с удовольствием читаю отчеты об успешно отраженных нападениях на сервера.
Есть несколько инструментов для Firefox. Например, Firebughttp://www.getfirebug.com/ , Tamper Datahttp://tamperdata.mozdev.org/ , Hack Barhttps://addons.mozilla.org/firefox/addon/3899 . Посмотрите на них и больше никогда не доверяйте только лишь одному HTML.
В Firebug, например, скрытые элементы редактируются на ура. Аттрибуты maxlength, disabled, readonly снимаются очень просто. HTML-код, сгенерированный на JavaScript просматривается полноценно, а изменения отражаются немедленно.
Кстати, Firebug в первую очередь прекрасное средство для отладки.
Все верно выставленные параметры и JavaScript-обработчики (не в качестве защиты) нужны для нормального пользователя, чтобы он понял, сколько он может вводить, где нельзя нажать и т.п. А ненормальный пользователь всё равно построит запрос руками. Собственно, остальная часть статьи во многих местах рассказывает вам, как защититься от построенного самостоятельно поддельного запроса.
цепочка кодирований и шифрований спасет вас, то я напомню вам, что рано или поздно код должен быть выполнен браузером в нормальном виде, и когда-нибудь таковым он все-таки попадает в eval (параметр eval строка интерпретируется и выполняется как код JavaScript). Я ради прикола иногда не отказываю себе в удовольствии распотрошить очередной вирус на JS, так вот даже их создатели ничего не могут поделать с сокрытием алгоритма.
Как вам перспектива массовой накрутки счетчика злоумышленником, либо добавление записей флудером при помощи метода HEAD? Копеечный трафик, а какой эффект!
Пример неправильного кода:
Чтобы избежать обработки регулярных метасимволов, нужно писать переменные между \Q и \E:
Есть функция под названием quotemeta. Она подготавливает строку символов к безопасному помещению в регулярное выражение. Все не алфавитно-цифровые символы будут проэкранированы обратным слэшэм.
Не может быть двух пользователей с совпадающими логинами, email или одинаковыми паспортными данными.
Не должно появиться двух пунктов меню или в списке на одном уровне с полностью совпадающим названием.
Не может существовать двух предметов под названием «Физическая география» с разными id.
И так далее. Можно привести массу примеров, главное вспоминать об этом принципе при проектировании всего нового. В борьбе с неуникальностью помогут уникальное индексирование или ручная проверка select-ом перед вставкой.
Последнее время стало модно проверять данные с помощью Ajax прямо во время заполнения форм.
Делая так, вы не только заблаговременно предупредите пользователя об ошибке, но и избавите его от лишних действий ему не придётся возвращаться на предыдущую страницу кнопкой Back, Backspace или JavaScript-ссылкой, рискуя потерять введённые данные, потому как не все браузеры одинаково бережно относятся к данным форм на предыдущих страницах, либо сами избавляетесь от лишней работы по генерации в ответ на POST этой же формы, но с помеченными ошибками.
Примеры таких функций:
И тому подобные.
Примеры использования:
Но этого недостаточно. Всегда дотошно представляйте себе ситуацию, обдумайте типичные ошибки и опечатки. В сообщении об ошибке покажите пример правильно заполненного поля. Наконец, включите логику.
Вот пара простых примеров:
Если вы спрашиваете у пользователя, когда он создал свой сайт, не позволяйте ему указать 1634 год (тогда интернета вроде не было) или дату в будущем.
Или вы спрашиваете возраст пользователя. Не нужно позволять ему указывать 300 лет. К сожалению, столько не живут. Правда в этом конкретном случае лучше быть оптимистом, да и деваться некуда нужно ставить с запасом. Зато представьте себе, какая радость, когда какой-то пользователь пожалуется на ограничение в 150 лет :)
HTML:
Perl:
Можно сделать обёртку:
метод quote интерфейса DBI, если текст, введенный пользователем, нужно использовать в SQL-запросах. Либо биндинг параметров, что обязательно для BLOB-полей и полезно для простого текста. Этим вы будете защищены от SQL-Injection атак.
Примеры с биндингом:
Пример с quote:
Смешивать quote и биндинг нельзя!
Пример. Представьте себе, что вашу форму заполнили вот так:
А если там будет что-то вроде этого. Как вам?
Защищайтесь даже от не вполне очевидных опасностей, скажем, от поля User-Agent запроса (который часто светится в логах или статистике, что, как правило, дело админское, а там XSS еще более опасен).