Пользователь
13,6
рейтинг
21 февраля 2013 в 01:30

Разработка → На пути к созданию безопасного веб-ресурса. Часть 2 — разработка tutorial

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

Дыра в безопасности не была исправлена, так как продукт-менеджеры хотят новую фичу


Программисты


Логично начать именно с них, с их знаний и опыта. Вина самого сотрудника в том, что он не обладает достаточными знаниями о security-разработке минимальна. Основная ответственность на руководстве, HR и ком-нибудь еще. Проблема возникает на этапе набора сотрудников. Рассмотрим типичное собеседование, даже основываясь на гайдах, которые выкладывались здесь, на Хабре:


Никто нигде (в т.ч. последняя статья, в комментах) не упомянул ни разу о security-аспектах. «Рыба гниет с головы» и это факт. Что я предлагаю? При наборе сотрудников, во-первых, самому разобраться хотя в базовых моментах программирования с т.ч. зрения безопасности и позадавать по ним вопросы. И предлагаю следующие вопросы, ответы на которые (а главное — детальность объяснения) даст хоть какую-нибудь картину о знаниях разработчика в сфере безопасности. Выберем какие-нибудь типичные конструкции и уязвимости в них:

XSS

<?php
$name = $_GET['name'];
echo "Hello, <b>$name</b>!";
?>

Спрашиваем мнение. Неважно, знает ли соискатель reflected это, stored или DOM XSS. Главное, что он понимает, что подобные конструкции недопустимы (и будет круто, если знает последствия таких конструкций. А еще круче — решение). Задачу можно усложнить с подстановкой данных через JS, полученных откуда-либо.

SQLi

<?php
$value = "id = ".$_GET['id'];
$select->where($value);
?>

Это отсылка к одной из моих предыдущих статей (проблема не надумана, а была взята из практики). И так, мы ищем специалиста по Zend, он круто отвечает на все вопросы, но… Вполне нормально относится к подобным конструкциями. Или подставляет в where массив, пришедший из GET/POST через implode.

File Upload

<?php
if ($_FILES["file"]["type"] == "image/gif") || $_FILES["file"]["type"] == "image/jpeg" || $_FILES["file"]["type"] == "image/png") {
// Uploaded file is image, all ok
move_uploaded_file ...
}
?>

Загрузка картинки. Люди, имеющие хоть какой-нибудь опыт сраз скажут — что так уже никто не пишет. $_FILES[«file»][«type»] присваивается значение из HTTP, которое легко «подделывается». Ну да ладно, кандидат говорит, что меняем просто на «file — ib» или используем PEAR/Zend для этого и дело с концом (при этом он ссылается на stackoverflow). Но и тут он будет не прав (но уже лучше). Довольно легко создается evil.php файл, содержащий php-код, при этом имеющий заголовки изображения. Так что тут нужно и проверять заголовки уже принятного файла (через `file`, PEAR или Zend, например), и задавать ему расширение, на основе опредленного mime-type.

Хочу сказать, что неверные (неточные) ответы не должны быть решающими при принятии сотрудника (это мнение основывается исходя из рациональных побуждений, а не с точки зрения безопасности), но имейте ввиду, что сотруднику нужно изучить определенный материал в этой области. И первое время нужно проверять его код, особенно в каких-то важных моментах (как загрузка файлов).

А еще у нас есть уже принятые сотрудники. С ними нужно вести отдельную работу и периодически «давать жару», разбирая какой-нибудь найденный уязвимый код при всех. Или хотя бы почтовой рассылкой с ссылками, что почитать на эту тему.

И так, переходим от человеческого фактора к техническому.

Иерархия

Начну со структуры каталогов. Она практикуется многими:

example.com
    ├── app
    │   ├── config.ini
    │   ├── framework
    │   └── src
    │       ├── controller
    │       ├── model
    │       └── view
    ├── crontab
    │   ├── daily_flush_stat.php
    │   └── weekly_remove_cache.sh
    └── htdocs
        ├── css
        ├── img
        ├── index.php
        └── js

Подобную структуру каталогов использую и я, и не вижу никаких проблем с ней. Начнем с последнего пункта — htdocs. В htdocs у нас всего 1 php скрипт — index.php (отсылка на первую часть статьи), эдакий bootsrtap, который стартует все приложение и отдает нужный функционал в зависимости от location. Там же лежит вся статика и upload от пользователей. Выполнимым к php остается всего 1 файл, и это замечательно!

app — application, вынесен за htdocs, это исключает в файлах модулей за ненадобностью подобные конструкции:

if (!defined('IN_SITE')) die ("Hack attempt!");

Прямой доступ к файлам в принципе невозможен. Так же нам не надо создавать кучу пустых index.html в каждой папке, если по каким-то неведомым причинам у нас включено индексирование в директориях и мы не можем это отключить.

config.ini так же не доступен из веба, соответственно не отдастся plain-text'ом по прямому обращению к нему.

Cron-скрипты (или скрипты для jenkins'a) так же удобно хранятся в нужной нам директории.

Код приложения

Разберем наиболее популярную схему использования шаблонов проектирования — MVC и решим, где у нас и что будет.

Model

Валидация. Многое зависит от того, что принято в вашей команде. Обычно, все же, сюда выносят валидацию данных при инициализации модели. Но это может быть и с успехом сделано в другом месте (service как пример).

View

Здесь я рассмотрю извечный вопрос — где конвертировать спецсимволы HTML? Например, phpbb это делает при записи данных в базу и как итог — данные занимают большее место. Сообщение
WOW >>> "NEW NEW NEW"
займет не 42 байта (в UTF8), а 82, так как будет иметь вид
WOW &gt;&gt;&gt; &quot;NEW NEW NEW&quot;

А так же может привести к ошибкам порядка валидации данных (которые и присутствуют у phpbb).
Моё мнение, что данные нужно записывать в том виде, в котором они пришли. И конвертировать спец. символы на выходе, в шаблонизаторе.
Конечно, непосредственная конвертация спец. символов при записи в базу является более безопасной, чем конвертирование их на выходе. Т.к. в одном месте разработчик все сделал правильно, а в другом месте — забыл (или выводил их другой разработчик). Но первый вариант можно считать костылем.

Controller

Основные уязвимости чаще всего встречаются именно в местах с манипуляцией данными. Здесь я хочу повториться о том, о чем писал еще в своих первых статьях, и предложить использовать следующую конструкцию:

try {
    // try something
} catch (Exception $e) {
    echo "Сожалеем, но произошла ошибка. Разработчики уже уведомлены и в скором времени все исправят!"
    errorLog($e->getMessage());
}

Где errorLog() — добавит запись об ошибке в базу, вышлет письмо на dev@example.com или что-то еще. Вы всегда будете в курсе всех проблем, которые случаются на проекте. Так же, если мы используем New Relic (о котором было сказано в первой части статьи), то мы получим подобный красивый мониторинг:


Cкрин с примером логирования ошибки, когда кто-то пытался подобрать адрес phpmyadmin, например, при помощи использования nikto

Время, лог, и количество возникновения данной ошибки. error.log в современном варианте.

Итерации

Если ваш продукт обновляется итерациями, то в подобную организацию процесса легко вписывается подход security-проверки выгружаемого кода на production. Делается полный diff и просматривается опытными программистами или security-отделом (человеком).

Framework, CMS/CMF

Разработка продукта на фреимворке — не панацея безопасности (особенно это подтвердил RoR с самого начала года). Использование самых популярных движков и полное использование их API при разработке модулей — так же не панацея (WordPress => 3.5 XMLRPC pingback additional issues).

Выводы?

Мое мнение остается прежним, что лучше весь код писать с нуля, при этом уже имея опыт в безопасности (а лучше именно во взломе/пентесте). Но, конечно, это практически неуместно в современном мире, так как это требует довольно больших дополнительных затрат для бизнеса (да и найти сразу столько специалистов довольно сложно).
Кстати, на эту тему у меня есть отличный график (о котором я узнал от Алексея Бабенко из Информзащиты, который сам, в свою очередь, узнал о нем на одной из заграничных стажировок по безопасности)


Оптимальный уровень безопасности при минимальных затратах. Картинка найдена здесь

Из которого можно сделать выводы, что начальные вложения дают быстрый и резкий скачок в безопасности. Но чем больше будут вложения, тем все меньше будут уменьшаться риски.

Серии:
Sergey Belov @BeLove
карма
236,7
рейтинг 13,6
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (20)

  • +2
    Позвольте поинтересоваться, из какого фильма первая картинка?
    • +9
      Если не ошибаюсь, то из сериала IT Crowd.
  • +1
    О чем эта статья?
    Классификация уязвимостей? Тогда где отсутствие проверки авторизации (не аутентификации) или неконтроллироемуе массовое присваивание в модели? На которые приходится львиная доля ошибок.
    Похоже на список «говорю, о чем вспомнил».
    Таких «списков» великое множество, однако детальный качественный анализ каждого из пунктов встретишь редко.
  • +4
    Разработка продукта на фреимворке — не панацея безопасности (особенно это подтвердил RoR с самого начала года) ...

    Мое мнение остается прежним, что лучше весь код писать с нуля, при этом уже имея опыт в безопасности


    Ни одна организация никогда не будет настолько крута, как многотысячное open-source-сообщество (прошу только не вспоминать сейчас Windows vs Linux — я не о таких масштабах).

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

    Это фантастика и самоуверенность, которую вы подкрепляете очень спорным аргументом про RoR и WP: если в системе нашли несколько ошибок, это ещё не значит, что система дырявая. Может быть просто очень хорошо искали.
    • 0
      если в системе нашли несколько ошибок, это ещё не значит, что система дырявая
      По-моему, это станет комментарием месяца.
      • 0
        поясните свою демагогию, пожалуйста.
        • 0
          Как мне кажется, если в системе есть ошибки, связанные с безопасностью, то система «дырявая». И это даже хорошо, что находят такие ошибки.
          yandex.ru/yandsearch?text=theshock+абсолютная+уязвимость
          «Абсолютная уязвимость. Все версии. Все полномочия. Просто шедевр. Браво!»
          • +1
            в любой программной системе минимум столько вероятных уязвимостей, сколько в ней строк кода. если где-то их не находят, это не значит, что их там нет. и будьте вы хоть двадцать раз супер-крутым infosec-специалистом… вы можете прийти на работу невыспавшимся, вас кто-то может отвлечь, и проявляется человеческий фактор. и тут уже вы допускаете те ошибки, которые фреймворки не дают допускать по определению архитектуре.
            • 0
              Интересно, что вы пытаетесь донести? Что разработка на фреймворке — панацея безопасности? Или что «абсолютная уязвимость» в RoR не делает систему «дырявой» (потому что это RoR)?
              • +5
                я пытаюсь донести то, что писать велосипеды потому, что они безопаснее — сущий бред. фреймворки и cms уровня WP — не панацея безопасности, вы всегда должны иметь свою голову на плечах. но, тем не менее, с ними гораздо безопаснее, чем без них. вероятность найти в них такую «абсолютную уязвимость» гораздо ниже, чем в вашем супер-секьюрном велосипеде.
                • 0
                  по части панацеи вы всё-таки соглашаетесь с автором?
                  и вот про вероятность тоже небольшое дополнение: «в любой программной системе минимум столько вероятных уязвимостей, сколько в ней строк кода.» наверное, в велосипеде будет поменьше строк кода, чем в универсальных фреймворках и cms.
                  • 0
                    вы цепляетесь к словам. вы прекрасно понимаете, что повторив это обобщённое выражение автора про панацею, я выражаю почти обратную точку зрения.
                  • 0
                    Извините. Но вы и в повседневной жизни строите велосипеды? Когда вам хочется кушать, вы конструируете плиту, выращиваете продукты?

                    Если так фанатеть за написание всего с нуля. То и язык нужно писать свой и среду, и сервер и операционку. А под конец и железо своё делать.
                    Потому что это всё, тоже может иметь свои уязвимости.
    • 0
      Согласен, если команда хотя бы > 5 человек, то разрабатывать нужно на фреимворке. Фреимворк в данном случае сократит риски намного больше, чем уменьшится риск от того, что приложение разрабатывается с нуля и его не взломают именно через уязвимости в фреимворке.
  • 0
    Автор, может быть, стоит в конце поста привести какой-нибудь список источников (кроме «набивайте шишки сами», конечно :) ), чтобы почитать и углубить знания по теме для заинтересовавшихся темой?
  • 0
    Не думаю, что писать код с нуля лучше, чем вариант не плодить сущностей и пользоваться проверенными своими или чужими решениями.
    • 0
      Я думаю имелось ввиду как раз свое, проверенное решение.
  • 0
    А я всегда считал что экранирование символов перед записью в базу данных как раз является менее безопасным.
  • 0
    >>Прямой доступ к файлам в принципе невозможен.

    есть ещё такая штука
    wiki.nginx.org/HttpCoreModule#internal
    в секции с fastcgi запретит запросы к скриптам напрямую

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.