СЕРГЕЙ ЯРЕМЧУК, фрилансер. Автор более 800 статей и шести книг. С «СА» с первого номера. Интересы: сетевые технологии, защита информации, свободные ОС
Технология AJAX: как насчет безопасности?
Один-единственный объект Java Script XMLHttpRequest изменил порядок взаимодействия пользователей с сервером. Если ранее для того, чтобы отправить данные, необходимо было нажимать кнопку, подтверждая действие, то теперь это будет сделано автоматически. Стоит заполнить поле, и браузер уже отправляет данные серверу, пользователь при этом не участвует. Удобство налицо, например, если в поисковике по мере ввода параметров поиска будут выводиться подходящие страницы, то таким образом можно регулировать параметры запроса на лету, добившись результата в меньшее время. Или, например, как в Gmail, можно на лету проверять правописание. При этом веб-приложение фактически ведет себя аналогично настольному.
Безопасность клиента
Все вроде бы хорошо, удобство налицо, но представьте, что при вводе произошла ошибка, например, пользователь механически ввел вместо одного почтового адреса другой. В старых системах у него всегда был бы шанс исправиться, теперь его, увы, уже нет. И в итоге провайдерский почтовый адрес уже висит на каком-либо форуме и через некоторое время попадет в базу данных спамеров. Возможно, это не самое страшное, что может произойти, но можно, например, представить ситуацию и похуже. Зашли на сайт, начали заполнять поля, ввели номер кредитной карточки, а затем сам сайт показался подозрительным, а ничего уже не изменишь. Или, как вариант, по ошибке был введен логин и пароль не к тому сайту, учитывая, что большинство пользователей не утруждают себя многочисленными комбинациями логин/пароль, можно получить данные для доступа совсем к другому ресурсу. При этом владельцы веб-сайтов могут собирать информацию о привычках пользователя. Фактически каждое нажатие клавиши, каждое движение мыши, щелчок, пауза при чтении информации могут быть перехвачены и отправлены на веб-сервер, и пользователь может и не знать об этом, но и сделать, собственно, ничего не сможет. То есть фактически технология AJAX позволяет контролировать действия пользователя, а раз такая возможность есть, то я сомневаюсь, чтобы ею никто не воспользовался.
Но это еще не все. Пользователи обычно бывают более внимательными при первоначальной загрузке страницы, когда обычно выполняется код страницы, контролируются сообщения межсетевого экрана, подозрительные системные события и прочее. Но теперь ситуация изменяется в корне. Все дело в том, что теперь любой код может быть выполнен и после загрузки страницы. Например, рассмотрим такой код:
xmlReq.onreadystatechange =
{
if ( xmlReq.readyState == 4 )
{
eval ( xmlReq.responseText );
}
}
И самое печальное, что теперь, проанализировав исходный код документа, нельзя до конца быть уверенным в лояльности того или иного сервиса. И все это на фоне повышения популярности атак, направленных на уязвимости в клиентских приложениях, в частности в веб-браузерах. Как бы то ни было, именно на безопасность клиентов при использовании технологии AJAX обращают внимание многочисленные эксперты.
Ошибки при программировании
AJAX-технология относительно молодая, и хотя уже сегодня можно найти тысячи примеров, разработчикам все равно приходится самостоятельно писать код как для сервера, так и для клиента практически в каждомом случае, и к тому же на разных языках. Это приводит к многочисленным ошибкам в реализации, часть которых обнаруживается только при эксплуатации приложения. К тому же не стоит забывать, что эту ситуацию усугубляют различия в поведении веб-браузеров, наличие плагинов (некоторые отладчики, о которых рассказано чуть ниже, перехватывают действие и подменяют своим) и прочее. Это приводит к увеличению кода, а значит, – к вероятному появлению ошибок в конкретной реализации. На сегодняшний день стандарт XMLHttpReques еще не принят, 5 апреля 2006 года World Wide Web Consortium опубликовал всего лишь его черновой вариант [13]. К тому же всегда найдутся особенные браузеры, разработчики которых не будут придерживаться рекомендаций WWWC, и некоторая часть пользователей все равно будет использовать старые версии браузеров, поэтому улучшений здесь в ближайшем будущем не предвидится.
А что сервер?
По сообщениям специалистов, занимающихся безопасностью, сегодня приблизительно 20 процентов уязвимостей приходятся именно на веб-приложения. Отмечается, что очень редкое приложение может похвастаться всего одной уязвимостью, большая же часть содержит несколько уязвимых мест. При этом большая часть уязвимостей (около 95%) приходится на cross-site scripting (XSS), т.е. подстановка чужого кода в текущий сеанс. Типичные эксплоиты могут включать: модификацию страниц (дефейс), переадресацию (например, для форм регистрации) и взаимодействие с сайтом от имени другого пользователя.
Нас в контексте статьи интересует последний пункт. Хотя стоит отметить, что при помощи XSS можно смоделировать любую ситуацию, которую возможно проделать при помощи JavaScript. Теперь представим такую ситуацию. Пользователь заполняет некую форму, AJAX отсылает запрос, сервер обрабатывает отправленные данные и возвращает ответ. Но что, если злоумышленник имеет возможность перехватить данные сеанса и скорректировать параметры запроса либо самому составить запрос, основываясь на анализе исходного кода и ответов сервера. Если во время своей работы сервер не будет дополнительно подстраховываться и контролировать поступающие данные на предмет их принадлежности конкретному пользователю, это может привести к утечке конфиденциальных данных. Одним из самых простых методов управления разрешениями является использование cookies. Когда объект XMLHttpRequest создает запрос, он возвращает все активные в настоящее время для этого сайта сеансовые cookies. Но это может быть выходом не для каждой ситуации. Например, запросы могут быть отправлены не тому серверу, на котором зарегистрировался пользователь, а на другой сервер, где привилегии никак не подтверждены. Если ранее браузер просто отправлял ему форму, то теперь происходит двусторонний обмен данными (хотя некоторые браузеры могут блокировать такое поведение), и самое главное, что второй ресурс может не иметь активных cookies.
В некоторых скриптах, встречающихся на форумах, приходящие данные персонализируются на основании некоего идентификатора пользователя (ID) или токена. Токен включен как заголовок в запросах, сделанных объектом XMLHttpRequest. Он должен вести себя аналогично сеансовому токену и обеспечивать доступ к защищенному ресурсу. Но злоумышленнику ничего не стоит сгенерировать запрос, указав перехваченный при помощи сниффера идентификатор, либо просто попытаться его подобрать и получить в результате доступ к информации. Если все же использование других механизмов неудобно либо накладно, то постарайтесь избегать последовательных ID, а сам ID сделать менее предсказуемым. Этим вы хотя бы затрудните его подбор.
Самое интересное, что никаких особых инструментов для перехвата не надо, достаточно иметь под рукой веб-браузер. Тот же Firefox позволяет просмотреть исходный код документа, а, использовав плагины FireBug (рис. 1) и Greasemonkey, можно не только просматривать исходный код полученных документов, но и редактировать их, регистрировать AJAX-запросы и проверять ответы сервера. Причем это далеко не единственные плагины к этому веб-браузеру, предназначенные для отладки веб-приложений.
Рисунок 1. При помощи FireBug можно просматривать AJAX-запросы
Наверное, самой большой ошибкой при использовании технологии AJAX является недостаточный контроль над вводимыми данными, возможно, из-за незначительного объема обрабатываемой информации. Это не может не приводить к появлению характерных уязвимостей. И хотя на сегодняшний момент в AJAX найденные ошибки можно пересчитать по пальцам, но они уже есть и, несомненно, это только начало. Самое печальное, что подобные ошибки встречаются не только в любительских скриптах, но и в инструментах разработчиков.
Например, CPAINT (Cross-Platform Asynchronous INterface Toolkit) [7], который представляет собой пакет AJAX-разработчика, распространяемый по лицензии GNU GPL и поддерживающий работу с несколькими языками. В нем обнаружена уязвимость, позволяющая злоумышленнику выполнить произвольные ASP/PHP-команды. Аналогичная уязвимость была найдена и в PAJAX [8], который представляет собой структуру, облегчающую создание отдаленных PHP-объектов в JavaScript. Для связи между объектами JavaScript, которые выполняются в браузере, и реализации их PHP-аналога на сервере используется AJAX. Или, например, AJAX Spell Checker (ajax-spell), в котором обнаружена уязвимость, позволяющая провести XXS-атаку [5].
Небольшой объем данных, обычно пересылаемый при помощи AJAX, часто приводит к тому, что им могут просто не придать значения, забывая о их ценности. И если ранее всю форму полностью направили бы через SSL, то теперь, возможно, с этим возиться никто не будет, особенно на фоне того, что большая часть передаваемых и принимаемых данных действительно не имеет большой ценности. Но стоит отметить, что уже появились наработки [11] по шифрованию информации, передаваемой при помощи AJAX.
Кроме того, бездумное использование AJAX может привести к возрастанию нагрузки на сервер. Так, если раньше форма отсылалась на сервер всего один раз после заполнения всех параметров, то теперь запросы поступают постоянно. И если скрипт написан неправильно, с ошибками или пользователь повел себя не так, как задумывал разработчик (а они обычно почему-то так всегда и поступают), то сервер может быть завален запросами. Без тщательного планирования и тестирования написанных приложений здесь явно не обойтись.
Что имеем?
Новая архитектура предполагает и доселе неизвестные проблемы. Особенное беспокойство вызывает возможность нападения на клиентские системы, пользователи которых, как правило, подготовлены хуже и защищенность систем ниже. Можно даже предположить появление в недалеком будущем дополнительных настроек в веб-браузере, при помощи которых пользователь сможет контролировать AJAX-запросы, как это сегодня делается для cookies. Но как бы то ни было, не смотря на это, технология AJAX уже применяется на тысячах серверов и их количество постоянно растет. Отказаться от нее вероятно уже не нельзя, да и глупо. Один из соавторов книги «Ajax in Action» Эрик Паскарелло (Eric Pascarello) в интервью SearchWebServices.com дал следующие рекомендации для разработчиков AJAX которых и стоит придерживаться:
- Если используется аутентификация пользователя, убедитесь в проверке на странице запроса.
- Проверьте возможность SQL-инъекции.
- Проверьте возможность JavaScript-инъекции.
- Храните логику работы на севере.
- Не думайте, что каждый запрос реальный.
- Проверяйте данные с подтверждением.
- Проверьте правильность информации в заголовке запроса.
И тестирование, тестирование и еще раз тестирование. Успехов.
Ссылки, литература:
- Using the XMLHttpRequest Object and AJAX to Spy On You – http://www.devx.com/webdev/Article/28861.
- Security in an AJAX World – http://www.whirlycott.com/phil/2005/04/15/security-in-an-ajax-world.
- Архив проекта ModSecurity – http://www.modsecurity.org/arhive.
- «XMLHttpRequest allows dangerous request headers to be set», Bugzilla bug 302263 – https://bugzilla.mozilla.org/show_bug.cgi?id=302263.
- Описание уязвимости в AJAX Spell Checker – http://www.securityfocus.com/bid/13986/references, http://secunia.com/15737, http://www.security.nnov.ru/Jdocument503.html?l=RU.
- Описание уязвимости в CPAINT – http://secunia.com/advisories/16462.
- Домашняя страница CPAINT – http://sourceforge.net/projects/cpaint.
- Домашняя страница PAJAX – http://www.auberger.com/pajax.
- Плагин Greasemonkey – http://ftp.mozilla.org/pub/mozilla.org/extensions/greasemonkey/greasemonkey-0.6.4-fx.xpi.
- Плагин FireBug – http://releases.mozilla.org/pub/mozilla.org/extensions/firebug/firebug-0.3.2-fx+fl.xpi.
- Proof of Concept: Browser-Based Field Encryption With Blowfish Via Ajax – http://smokey.rhs.com/web/blog/PowerOfTheSchwartz.nsf/plinks/RSCZ-6CATX6.
- Родионов В. AJAX: заработавший Javascript. – Журнал «Системный администратор», № 12, 2005 г. – 66-69 с. – http://www.samag.ru/cgi-bin/go.pl?q=articles;n=12.2005;a=13.
- Черновой вариант класса XMLHttpRequest, описывающий его интерфейс и поведение, – http://www.w3.org/TR/2006/WD-XMLHttpRequest-20060405.