Что-то происходит. Люди недовольны. Призрак гражданских беспорядков преследует наши программистские сообщества.
Впервые значимое число веб-разработчиков открыто ставят под сомнение веб-платформу. Вот характерная статья и обсуждение. Вот другая статья. И ещё одна. Я бы мог перечислить и больше, но если вы достаточно интересуетесь программированием, чтобы читать эту статью, то наверняка уже читали в этом году хотя бы одну напыщенную декламацию о современном состоянии веб-разработки. Эта статья не из таких. Я не могу соревноваться в издевательствах над существующим статусом-кво с людьми, которым приходится заниматься веб-разработкой каждый день. Это другая статья.
Это ты, хакер фронтенда
Я хочу поразмышлять о том, можно ли создать настолько хорошего конкурента вебу, что он в итоге заменит его и включит в себя, по крайней мере, для написания приложений. У веба есть ещё проблемы как у системы распространения документов, но не настолько серьёзные, чтобы о них беспокоиться.
Это первая из двух статей. В первой части рассмотрим глубокие, неразрешимые проблемы веб-платформы: я хочу убедить вас, что отказ от неё является единственным вариантом. В конце концов, невозможно решить проблему, если сначала не подвергнуть её анализу. Также кратко рассмотрим, почему сейчас стало политически приемлемо обсуждать такие вопросы, хотя они не являются чем-то новым.
Во второй части я предложу новую платформу для приложений, которую способна создать небольшая группа разработчиков за разумное время, и которая (IMHO) должна быть гораздо лучше, чем то, что мы имеем сейчас. Конечно, не все согласятся с последним. Согласиться с проблемами всегда проще, чем согласиться с решениями.
Часть 1. Поехали.
Веб-приложения. На что они похожи, а? Я могу перечислить кучу их проблем, но давайте остановимся на двух.
Вот хороший пост по Flux, последнему модному веб-фреймворку от Facebook. Автор обращает внимание, что Flux воссоздаёт модель программирования, которую использовала Windows 1.0, выпущенная в 1985 году. Microsoft использовала эту модель, потому что она подходила для медленных компьютеров, но под неё было настолько неудобно программировать, так что не прошло и десятилетия, как выросла целая экосистема продуктов (вроде OWL), позволяющих абстрагироваться над лежащей в основе системой сообщений WndProc.
Одна из причин, почему React/Flux работают таким образом — очень медленные движки веб-рендеринга. Это правда, и конечный видимый пользователю результат лишь немного более замысловатый, чем пользователь Windows мог видеть 20 лет назад:
Windows 98
Конечно, разрешение экрана стало больше. Изменились оттенки серого, которые нам нравятся. Но UI, который вы видите вверху, по сложности довольно похож на UI, который вы видите внизу:
Даже мода на иконки не изменилась! Windows 98 представила новый тренд плоских иконок в оттенках серого, в то время как предыдущие были цветными, плотно упакованными пиксельными изображениями.
Но Office 2000 вполне довольствовался CPU на 75 МГц и 32 МБ памяти, в то время как Google Docs со скриншота использует CPU на 2,5 ГГц и почти в десять раз больше памяти.
Если бы мы получили десятикратный прирост в производительности и функциональности, это было бы простительно, но мы его не получили. Платформы разработки в 1995 году по умолчанию обладали всем нижеперечисленным, только для начала:
Многие из этих функций появились на веб-платформе только в последние несколько лет, и часто весьма поверхностно. Веб-приложения не могут использовать реальные сокеты, так что вместо этого серверы приходится переводить на поддержку «веб-сокетов». Такие базовые вещи как компоненты UI — это тихий ужас. Не существует серьёзной Web IDE, а насчёт смешивания разных языков программирования… ну, вы можете попытаться всё скомпилировать в JavaScript. Иногда.
Разработчики любят писать веб-приложения по одной причине — ожидания пользователей от таких приложений исключительно низки. От приложений для Windows 95 вы ожидаете наличия пиктограмм, перетягивания мышкой, отмены произведённых действий, ассоциаций с расширениями файлов, нормальных сочетаний «горячих клавиш», полезной деятельности в фоновом режиме… и даже работы в офлайне! Но это самые простые приложения. По настоящему крутой софт мог встраиваться в документы Office или расширять функциональность Explorer, или допускать расширение функциональности произвольными плагинами, которые изначально неизвестны автору программы. Веб-приложения обычно не делают ничего подобного.
Всё это накапливается. Я чувствую себя гораздо продуктивнее, когда пишу десктопную программу (даже с учётом разных «налогов», которые вам придётся платить, вроде изготовления пиктограмм для своих типов файлов). Использовать я тоже предпочитаю их. И из разговоров с другими знаю, что я не один такой.
Думаю, что веб стал таким, потому что HTML вышел с вполне вразумительной философией дизайна и инструментарием как платформа для документов, но в качестве платформы для приложений HTML пришлось закреплять на соплях, и ничего хорошего до сих пор не получилось. Поэтому не существует самых базовых вещей вроде ассоциаций файлов. Зато в HTML5 имеется пиринговый видеостриминг, потому что Google хотела сделать Hangouts, ну а приоритеты Google — это главное в том, какие функции добавлять в стандарт. Чтобы избежать такой проблемы, нам нужна платформа, которая изначально спроектирована с мыслью о приложениях, а затем, может быть, добавить сверху ещё и документы, а не наоборот.
В конце 1990-х ужасная реализация ЯП нависла над программной индустрией: уязвимости безопасности в программах C/C++ перестали быть редкими ошибками, которые можно исправить по отдельности. Они появились повсюду. Люди стали понимать, что если код C/C++ выставить в интернет, неизбежно появятся эксплоиты.
Можно оценить невинность того мира, если почитать отчёт SANS по сетевому червю Code Red от 2001 года:
В Windows существовали автоматические обновления, но если я правильно помню, отключенные по умолчанию. Идея, что программа может изменяться без ведома пользователя, была эдаким табу.
Первые признаки заражения Blaster
Постепенно индустрия начала меняться, но с криками и протестами. В то время пользователи Linux и Mac частенько говорили, что это вообще чисто проблема Microsoft… а их системы созданы некими сверхпрограммистами. Так что в то время как Microsoft приняла факт, что столкнулась с экзистенциальным кризисом и ввела «жизненный цикл безопасной разработки» (гигантская программа переобучения и новый процесс), её конкуренты практически бездействовали. Редмонд добавил файрвол в Windows XP и выпустил сертификаты для подписи кода. Мобильный код запретили. Когда стало ясно, что уязвимости в безопасности идут бесконечным потоком, ввели периодический выпуск патчей “Patch Tuesday”. Умные хакеры продолжали делать открытия, как эксплуатировать известные ранее баги, которые казались безопасными, и как обходить защиты от эксплоитов, ранее казавшиеся надёжными. Сообщества Mac и Linux начали постепенно выходить из спячки и осознавать факт, что они не являются волшебным образом защищёнными от вирусов и эксплоитов.
Последним поворотным моментом стал 2008 год, когда Google выпустила Chrome, важный проект с той точки зрения, что они потратили массу усилий на создание сложной, но совершенно незаметной песочницы для движка рендеринга. Другими словами, лучшие в индустрии разработчики признали, что они не способны написать безопасный код C++ независимо от того, как упорно будут над ним работать. Такой тезис и изолированная архитектура стали стандартами де-факто.
К сожалению, веб не вывел нас на благословенную землю безопасных приложений. Хотя веб-приложения в каком-то роде изолированы от материнской ОС, и это хорошо, но сами приложения вряд ли более надёжны, чем код Windows от 2001 года. Вместо того, чтобы навсегда избавиться от доставшихся по наследству проблем, веб просто заменил один тип переполнения буфера другим. В десктопных приложениях эксплуатировались уязвимости типа двойного освобождения одной и той же памяти (double free), уязвимости целостности стека (stack smash), использования памяти после освобождения (use after free) и прочие. Веб-приложения исправили их, но представили собственные такие же ошибки: инъекции SQL, XSS, XSRF, инъекции заголовков, смешение типов MIME и так далее.
Всё это ведёт к простому тезису:
Невозможно написать безопасное веб-приложение.
Не будем педантами. Я не говорю буквально обо всех веб-приложениях. Да, можно написать безопасный HTML Hello World, флаг в руки.
Я говорю о реальных веб-приложениях пристойного размера, написанных в реалистичных условиях, и это заявление далось нелегко. Понимание пришло ко мне после восьми лет работы в Google. Там я наблюдал, как самые лучшие и талантливые веб-разработчики снова и снова выдают код с эксплуатируемыми багами.
Отдел безопасности Google — один из лучших в мире, может и лучший, и для внутренней учебной программы они выпустили это полезное руководство с перечислением самых популярных ошибок веб-разработки. Вот их совет, как безопасно отправлять данные для отображения в браузере:
Чтение такой забавной охоты на ведьм и фольклора всегда вызывает у меня улыбку. Это должно быть шуткой, но в реальности здесь базовые вещи, которые обязан знать каждый веб-разработчик в Google, просто чтобы вывести какую-то информацию на экран.
На самом деле вы можете сделать всё вышеперечисленное, но этого будет недостаточно. Атака HEIST позволяет украсть данные из веб-приложения, которое безошибочно реализовало все меры защиты. Она эксплуатирует неустранимые изъяны архитектуры в самой веб-платформе. Конец игры.
Не совсем! Всё ещё хуже! Защита оконечных точек REST/JSON — только одна из разнообразных проблем безопасности, которые должен понимать современный веб-разработчик. Имеются десятки других (вот интересный пример и ещё один прикольный).
По опыту могу сказать, что невозможно нанять веб-разработчика, который хотя бы слышал обо всех этих подводных камнях, не говоря уже о разработчике, который способен от них защититься. Вот мой вывод: если вы не можете найти веб-разработчика, который понимает, как писать безопасные веб-приложения, то написать безопасное веб-приложение невозможно.
Практически все проблемы безопасности в вебе объясняются несколькими ключевыми проблемами архитектуры:
Потеря контроля над размером буферов — классический источник уязвимостей в программах C, а в вебе возникла в точности такая же проблема: все инъекции XSS и SQL основаны на создании путаницы насчёт того, где начинается буфер для кода и заканчивается буфер для данных. Веб крайне зависим от текстовых протоколов и форматов, так что приходится неизменно парсить буферы, чтобы определить их размер. Это открывает целую вселенную проблем с экранированием (escaping), заменой и прочими вещами, которые совсем необязательны.
Исправление: Размер всех буферов должен иметь метку числом: от базы данных до сервера фронтенда и интерфейс пользователя. Не должна возникать необходимость что-то сканировать в поиске волшебных символов и смотреть, где они заканчиваются. Обратите внимание, что для этого требуются бинарные протоколы, форматы и логика UI по всему стеку.
HTTP и HTML спроектированы для документов. Даже Егор Хомаков сумел сломать двухфакторную аутентификацию Authy, просто набрав “../sms” в поле ввода кода SMS. Ему это удалось, потому что подобно всем веб-сервисам Authy создана на стеке для гипертекста, а не программного обеспечения. Обход каталога имеет смысл, если вы реально имеете доступ к директориям с файлами HTML, как и задумал сэр Тим. Если же вы представляете программный API как «документы», то обход директории может стать фатальным.
REST был достаточно ужасен уже тогда, когда возвращал XML, но в наше время XML вышел из моды и теперь веб использует JSON — формат, настолько плохо спроектированный, что у них в вики целый раздел посвящён проблемам безопасности.
Исправление: Прекратим притворяться, что REST — хорошая идея. REST — это плохая идея, которая перекручивает HTTP в то, чем он не является, только чтобы обойти ограничения браузера. Это ещё один инструмент, который перекрутили в то, чем он не должен быть изначально. Такое всегда плачевно заканчивается. Учитывая предыдущий пункт, клиент-серверные коммуникации должны использовать бинарный протокол, спроектированный специально для RPC.
Правило ограничения домена для веб-разработчика — ещё один опыт из книги Стивена Кинга. Цитата из вики:
SOP (same origin policy) стал результатом того, что Netscape прикрутила программный код к формату для документов. На самом деле это не имеет никакого смысла. Вы бы никогда не создавали платформу для приложений такого вида, если бы у вас было больше 10 дней времени на ввод её в эксплуатацию. Но на самом деле мы не можем их винить, потому что Netscape был стартапом, который работал в условиях острой нехватки времени, и как мы уже отметили выше, в то время вообще никто серьёзно не думал о безопасности. Результат 10-дневного марафона кодирования мог оказаться даже хуже.
Независимо от ваших симпатий, в сердце атаки HEIST лежит именно SOP, а атака HEIST ломает почти все веб-приложения такими способами, от которых, вероятно, никогда нельзя будет защититься, по крайней мере, без отказа от обратной совместимости. Это ещё одна причина, почему невозможно написать безопасное веб-приложение.
Исправление: Приложениям нужна ясная идентичность, и следует прекратить обмен друг с другом токенами безопасности по умолчанию. Если у вас нет разрешения на доступ к серверу, вы не должны иметь возможность отправлять ему сообщения. Это понятно на каждой платформе, кроме веба.
Есть масса других проблем с архитектурой, которые затрудняют создание безопасных веб-приложений, но вышеприведённых примеров, надеюсь, достаточно, чтобы убедить вас.
HTML5 — чума нашей индустрии. Хотя он хорошо делает некоторые вещи, эти преимущества легко повторяются на других платформах для веб-приложений, и практически никакие из ключевых проблем архитектуры веба невозможно устранить. Вот почему веб теряется на мобильных устройствах: при сравнении с конкурирующими платформами, которые действительно специально спроектированы, а не выросли естественным путём, разработчики почти всегда выбирают нативный вариант. Но за пределами мобильного мира у нас нет ничего хорошего. Мы отчаянно нуждаемся в способе удобно распространять изолированные, безопасные, автообновляемые приложения для настольных компьютеров и ноутбуков.
Десять лет назад меня бы распяли за написание такой статьи. Ожидаю некоторого ворчания и сейчас, но в последнее время стало социально допустимо критиковать веб. В прошлые времена веб был втянут в соревнование с проприетарными платформами вроде Flash, Shockwave и Java. Веб был открыт, но его выживание в качестве конкурентной платформы вызывало сомнения. Его итоговое возрождение и победа — это история, которая жмёт на все эмоциональные кнопки: открытость лучше, чем закрытость, коллективное владение лучше, чем проприетарный код, Давид победил Голиафа и так далее. У многих программистов выработалась настоящая племенная верность по отношении к нему. Добавление ко всему приставки «веб-» мгновенно делает это модным. Выскажите мнение, что Macromedia Flash хорош — и у вас могут отобрать удостоверение гика.
Но времена изменились. Веб так разжирел, что называть его открытым практически бессмысленно: у вас нет шансов внедрять HTML5, если в кармане отсутствуют несколько миллиардов долларов, которые вы хотите спустить. Консорциум W3C не прислушался к запросам пользователей и теперь стал ненужным, так что если вы не работаете в Google или Microsoft, то не можете как-то влиять на техническое развитие веба. Некоторые из ранее закрытых конкурирующих платформ теперь открылись. А экосистема JavaScript взрывается под весом своего собственного бессмысленного намолота.
Время вернуться назад к чистой доске. А теперь возьмите выпить и прочитайте следующую статью в серии: что последует за вебом?
Впервые значимое число веб-разработчиков открыто ставят под сомнение веб-платформу. Вот характерная статья и обсуждение. Вот другая статья. И ещё одна. Я бы мог перечислить и больше, но если вы достаточно интересуетесь программированием, чтобы читать эту статью, то наверняка уже читали в этом году хотя бы одну напыщенную декламацию о современном состоянии веб-разработки. Эта статья не из таких. Я не могу соревноваться в издевательствах над существующим статусом-кво с людьми, которым приходится заниматься веб-разработкой каждый день. Это другая статья.
Это ты, хакер фронтенда
Я хочу поразмышлять о том, можно ли создать настолько хорошего конкурента вебу, что он в итоге заменит его и включит в себя, по крайней мере, для написания приложений. У веба есть ещё проблемы как у системы распространения документов, но не настолько серьёзные, чтобы о них беспокоиться.
Это первая из двух статей. В первой части рассмотрим глубокие, неразрешимые проблемы веб-платформы: я хочу убедить вас, что отказ от неё является единственным вариантом. В конце концов, невозможно решить проблему, если сначала не подвергнуть её анализу. Также кратко рассмотрим, почему сейчас стало политически приемлемо обсуждать такие вопросы, хотя они не являются чем-то новым.
Во второй части я предложу новую платформу для приложений, которую способна создать небольшая группа разработчиков за разумное время, и которая (IMHO) должна быть гораздо лучше, чем то, что мы имеем сейчас. Конечно, не все согласятся с последним. Согласиться с проблемами всегда проще, чем согласиться с решениями.
Часть 1. Поехали.
Почему веб должен умереть
Веб-приложения. На что они похожи, а? Я могу перечислить кучу их проблем, но давайте остановимся на двух.
- Веб-разработка медленно повторяет 1990-е годы.
- Веб-приложения невозможно защитить.
Вот хороший пост по Flux, последнему модному веб-фреймворку от Facebook. Автор обращает внимание, что Flux воссоздаёт модель программирования, которую использовала Windows 1.0, выпущенная в 1985 году. Microsoft использовала эту модель, потому что она подходила для медленных компьютеров, но под неё было настолько неудобно программировать, так что не прошло и десятилетия, как выросла целая экосистема продуктов (вроде OWL), позволяющих абстрагироваться над лежащей в основе системой сообщений WndProc.
Одна из причин, почему React/Flux работают таким образом — очень медленные движки веб-рендеринга. Это правда, и конечный видимый пользователю результат лишь немного более замысловатый, чем пользователь Windows мог видеть 20 лет назад:
Windows 98
Конечно, разрешение экрана стало больше. Изменились оттенки серого, которые нам нравятся. Но UI, который вы видите вверху, по сложности довольно похож на UI, который вы видите внизу:
Даже мода на иконки не изменилась! Windows 98 представила новый тренд плоских иконок в оттенках серого, в то время как предыдущие были цветными, плотно упакованными пиксельными изображениями.
Но Office 2000 вполне довольствовался CPU на 75 МГц и 32 МБ памяти, в то время как Google Docs со скриншота использует CPU на 2,5 ГГц и почти в десять раз больше памяти.
Если бы мы получили десятикратный прирост в производительности и функциональности, это было бы простительно, но мы его не получили. Платформы разработки в 1995 году по умолчанию обладали всем нижеперечисленным, только для начала:
- Визуальный редактор UI с ограничениями макета и привязкой данных.
- Продвинутая поддержка программных компонентов на многих языках. Вы могли смешивать статически типизированный нативный код и языки сценариев.
- Выпускаемые исполняемые файлы были настолько эффективны, что работали на нескольких мегабайтах RAM.
- Поддержка построения графиков, тематизации, 3D-графики, программирования сокетов, интерактивной отладки…
Многие из этих функций появились на веб-платформе только в последние несколько лет, и часто весьма поверхностно. Веб-приложения не могут использовать реальные сокеты, так что вместо этого серверы приходится переводить на поддержку «веб-сокетов». Такие базовые вещи как компоненты UI — это тихий ужас. Не существует серьёзной Web IDE, а насчёт смешивания разных языков программирования… ну, вы можете попытаться всё скомпилировать в JavaScript. Иногда.
Разработчики любят писать веб-приложения по одной причине — ожидания пользователей от таких приложений исключительно низки. От приложений для Windows 95 вы ожидаете наличия пиктограмм, перетягивания мышкой, отмены произведённых действий, ассоциаций с расширениями файлов, нормальных сочетаний «горячих клавиш», полезной деятельности в фоновом режиме… и даже работы в офлайне! Но это самые простые приложения. По настоящему крутой софт мог встраиваться в документы Office или расширять функциональность Explorer, или допускать расширение функциональности произвольными плагинами, которые изначально неизвестны автору программы. Веб-приложения обычно не делают ничего подобного.
Всё это накапливается. Я чувствую себя гораздо продуктивнее, когда пишу десктопную программу (даже с учётом разных «налогов», которые вам придётся платить, вроде изготовления пиктограмм для своих типов файлов). Использовать я тоже предпочитаю их. И из разговоров с другими знаю, что я не один такой.
Думаю, что веб стал таким, потому что HTML вышел с вполне вразумительной философией дизайна и инструментарием как платформа для документов, но в качестве платформы для приложений HTML пришлось закреплять на соплях, и ничего хорошего до сих пор не получилось. Поэтому не существует самых базовых вещей вроде ассоциаций файлов. Зато в HTML5 имеется пиринговый видеостриминг, потому что Google хотела сделать Hangouts, ну а приоритеты Google — это главное в том, какие функции добавлять в стандарт. Чтобы избежать такой проблемы, нам нужна платформа, которая изначально спроектирована с мыслью о приложениях, а затем, может быть, добавить сверху ещё и документы, а не наоборот.
Веб-приложения невозможно защитить
В конце 1990-х ужасная реализация ЯП нависла над программной индустрией: уязвимости безопасности в программах C/C++ перестали быть редкими ошибками, которые можно исправить по отдельности. Они появились повсюду. Люди стали понимать, что если код C/C++ выставить в интернет, неизбежно появятся эксплоиты.
Можно оценить невинность того мира, если почитать отчёт SANS по сетевому червю Code Red от 2001 года:
«Представители Microsoft и агентств безопасности США провели пресс-конференцию, где инструктировали пользователей скачать патч с сайта Microsoft и назвали „гражданским долгом” скачивание этого патча. CNN и другие новостные издания после распространения Code Red предупредили пользователей о необходимости установить патчи на свои системы».
В Windows существовали автоматические обновления, но если я правильно помню, отключенные по умолчанию. Идея, что программа может изменяться без ведома пользователя, была эдаким табу.
Первые признаки заражения Blaster
Постепенно индустрия начала меняться, но с криками и протестами. В то время пользователи Linux и Mac частенько говорили, что это вообще чисто проблема Microsoft… а их системы созданы некими сверхпрограммистами. Так что в то время как Microsoft приняла факт, что столкнулась с экзистенциальным кризисом и ввела «жизненный цикл безопасной разработки» (гигантская программа переобучения и новый процесс), её конкуренты практически бездействовали. Редмонд добавил файрвол в Windows XP и выпустил сертификаты для подписи кода. Мобильный код запретили. Когда стало ясно, что уязвимости в безопасности идут бесконечным потоком, ввели периодический выпуск патчей “Patch Tuesday”. Умные хакеры продолжали делать открытия, как эксплуатировать известные ранее баги, которые казались безопасными, и как обходить защиты от эксплоитов, ранее казавшиеся надёжными. Сообщества Mac и Linux начали постепенно выходить из спячки и осознавать факт, что они не являются волшебным образом защищёнными от вирусов и эксплоитов.
Последним поворотным моментом стал 2008 год, когда Google выпустила Chrome, важный проект с той точки зрения, что они потратили массу усилий на создание сложной, но совершенно незаметной песочницы для движка рендеринга. Другими словами, лучшие в индустрии разработчики признали, что они не способны написать безопасный код C++ независимо от того, как упорно будут над ним работать. Такой тезис и изолированная архитектура стали стандартами де-факто.
Пришла очередь веб-платформы
К сожалению, веб не вывел нас на благословенную землю безопасных приложений. Хотя веб-приложения в каком-то роде изолированы от материнской ОС, и это хорошо, но сами приложения вряд ли более надёжны, чем код Windows от 2001 года. Вместо того, чтобы навсегда избавиться от доставшихся по наследству проблем, веб просто заменил один тип переполнения буфера другим. В десктопных приложениях эксплуатировались уязвимости типа двойного освобождения одной и той же памяти (double free), уязвимости целостности стека (stack smash), использования памяти после освобождения (use after free) и прочие. Веб-приложения исправили их, но представили собственные такие же ошибки: инъекции SQL, XSS, XSRF, инъекции заголовков, смешение типов MIME и так далее.
Всё это ведёт к простому тезису:
Невозможно написать безопасное веб-приложение.
Не будем педантами. Я не говорю буквально обо всех веб-приложениях. Да, можно написать безопасный HTML Hello World, флаг в руки.
Я говорю о реальных веб-приложениях пристойного размера, написанных в реалистичных условиях, и это заявление далось нелегко. Понимание пришло ко мне после восьми лет работы в Google. Там я наблюдал, как самые лучшие и талантливые веб-разработчики снова и снова выдают код с эксплуатируемыми багами.
Отдел безопасности Google — один из лучших в мире, может и лучший, и для внутренней учебной программы они выпустили это полезное руководство с перечислением самых популярных ошибок веб-разработки. Вот их совет, как безопасно отправлять данные для отображения в браузере:
Для исправления вы можете сделать несколько изменений. Любое из этих изменений предотвратит ныне возможные атаки, но если добавить несколько уровней защиты («глубокая защита»), вы защититесь от того, что какой-то из уровней не сработает в случае уязвимостей в браузере, которые найдут в будущем. Во-первых, используйте токен XSRF, как обсуждалось ранее, это гарантирует, что результаты JSON с конфиденциальными данными возвращаются только для ваших страниц. Во-вторых, ваши страницы ответа JSON должны поддерживать только запросыPOST
, чтобы предотвратить загрузку скрипта через тег <script>. В-третьих, следует убедиться, что скрипт неисполняемый. Стандартный способ сделать это — добавить к нему какой-нибудь неисполняемый префикс, вроде])}while(1);</x>
. Работающий в том же домене скрипт способен прочитать содержимое ответа и избавиться от префикса, но скрипты из других доменов не могут.
ПРИМЕЧАНИЕ: Сделать скрипты неисполняемыми не так просто. Возможно, исполняемость скриптов изменится в будущем, с появлением новых скриптовых функций и языков. Некоторые полагают, что можно защитить скрипт, превратив его в комментарий, то есть поместив в/*
и*/
, но всё не так просто. (Подсказка: что, если кто-то использует*/
в одном из своих сниппетов?)
Чтение такой забавной охоты на ведьм и фольклора всегда вызывает у меня улыбку. Это должно быть шуткой, но в реальности здесь базовые вещи, которые обязан знать каждый веб-разработчик в Google, просто чтобы вывести какую-то информацию на экран.
На самом деле вы можете сделать всё вышеперечисленное, но этого будет недостаточно. Атака HEIST позволяет украсть данные из веб-приложения, которое безошибочно реализовало все меры защиты. Она эксплуатирует неустранимые изъяны архитектуры в самой веб-платформе. Конец игры.
Не совсем! Всё ещё хуже! Защита оконечных точек REST/JSON — только одна из разнообразных проблем безопасности, которые должен понимать современный веб-разработчик. Имеются десятки других (вот интересный пример и ещё один прикольный).
По опыту могу сказать, что невозможно нанять веб-разработчика, который хотя бы слышал обо всех этих подводных камнях, не говоря уже о разработчике, который способен от них защититься. Вот мой вывод: если вы не можете найти веб-разработчика, который понимает, как писать безопасные веб-приложения, то написать безопасное веб-приложение невозможно.
Ключевая проблема
Практически все проблемы безопасности в вебе объясняются несколькими ключевыми проблемами архитектуры:
- Буферы, не соответствующие своему размеру
- Протоколы, разработанные для документов, а не для приложений
- Правило ограничения домена (same origin policy)
Потеря контроля над размером буферов — классический источник уязвимостей в программах C, а в вебе возникла в точности такая же проблема: все инъекции XSS и SQL основаны на создании путаницы насчёт того, где начинается буфер для кода и заканчивается буфер для данных. Веб крайне зависим от текстовых протоколов и форматов, так что приходится неизменно парсить буферы, чтобы определить их размер. Это открывает целую вселенную проблем с экранированием (escaping), заменой и прочими вещами, которые совсем необязательны.
Исправление: Размер всех буферов должен иметь метку числом: от базы данных до сервера фронтенда и интерфейс пользователя. Не должна возникать необходимость что-то сканировать в поиске волшебных символов и смотреть, где они заканчиваются. Обратите внимание, что для этого требуются бинарные протоколы, форматы и логика UI по всему стеку.
HTTP и HTML спроектированы для документов. Даже Егор Хомаков сумел сломать двухфакторную аутентификацию Authy, просто набрав “../sms” в поле ввода кода SMS. Ему это удалось, потому что подобно всем веб-сервисам Authy создана на стеке для гипертекста, а не программного обеспечения. Обход каталога имеет смысл, если вы реально имеете доступ к директориям с файлами HTML, как и задумал сэр Тим. Если же вы представляете программный API как «документы», то обход директории может стать фатальным.
REST был достаточно ужасен уже тогда, когда возвращал XML, но в наше время XML вышел из моды и теперь веб использует JSON — формат, настолько плохо спроектированный, что у них в вики целый раздел посвящён проблемам безопасности.
Исправление: Прекратим притворяться, что REST — хорошая идея. REST — это плохая идея, которая перекручивает HTTP в то, чем он не является, только чтобы обойти ограничения браузера. Это ещё один инструмент, который перекрутили в то, чем он не должен быть изначально. Такое всегда плачевно заканчивается. Учитывая предыдущий пункт, клиент-серверные коммуникации должны использовать бинарный протокол, спроектированный специально для RPC.
Правило ограничения домена для веб-разработчика — ещё один опыт из книги Стивена Кинга. Цитата из вики:
Способы проверки на ограничение домена и соответствующие механизмы не очень ясно определены для ряда пограничных случаев… исторически это вызывало немалое число уязвимостей в безопасности.
Вдобавок, многие легаси кросс-доменные операции, появившиеся до JavaScript, не подлежат проверкам на ограничение домена.
В конце концов, определённые типы атак, такие как DNS rebinding или серверные прокси, позволяют частично разрушить проверку имени хоста.
SOP (same origin policy) стал результатом того, что Netscape прикрутила программный код к формату для документов. На самом деле это не имеет никакого смысла. Вы бы никогда не создавали платформу для приложений такого вида, если бы у вас было больше 10 дней времени на ввод её в эксплуатацию. Но на самом деле мы не можем их винить, потому что Netscape был стартапом, который работал в условиях острой нехватки времени, и как мы уже отметили выше, в то время вообще никто серьёзно не думал о безопасности. Результат 10-дневного марафона кодирования мог оказаться даже хуже.
Независимо от ваших симпатий, в сердце атаки HEIST лежит именно SOP, а атака HEIST ломает почти все веб-приложения такими способами, от которых, вероятно, никогда нельзя будет защититься, по крайней мере, без отказа от обратной совместимости. Это ещё одна причина, почему невозможно написать безопасное веб-приложение.
Исправление: Приложениям нужна ясная идентичность, и следует прекратить обмен друг с другом токенами безопасности по умолчанию. Если у вас нет разрешения на доступ к серверу, вы не должны иметь возможность отправлять ему сообщения. Это понятно на каждой платформе, кроме веба.
Есть масса других проблем с архитектурой, которые затрудняют создание безопасных веб-приложений, но вышеприведённых примеров, надеюсь, достаточно, чтобы убедить вас.
Заключение
HTML5 — чума нашей индустрии. Хотя он хорошо делает некоторые вещи, эти преимущества легко повторяются на других платформах для веб-приложений, и практически никакие из ключевых проблем архитектуры веба невозможно устранить. Вот почему веб теряется на мобильных устройствах: при сравнении с конкурирующими платформами, которые действительно специально спроектированы, а не выросли естественным путём, разработчики почти всегда выбирают нативный вариант. Но за пределами мобильного мира у нас нет ничего хорошего. Мы отчаянно нуждаемся в способе удобно распространять изолированные, безопасные, автообновляемые приложения для настольных компьютеров и ноутбуков.
Десять лет назад меня бы распяли за написание такой статьи. Ожидаю некоторого ворчания и сейчас, но в последнее время стало социально допустимо критиковать веб. В прошлые времена веб был втянут в соревнование с проприетарными платформами вроде Flash, Shockwave и Java. Веб был открыт, но его выживание в качестве конкурентной платформы вызывало сомнения. Его итоговое возрождение и победа — это история, которая жмёт на все эмоциональные кнопки: открытость лучше, чем закрытость, коллективное владение лучше, чем проприетарный код, Давид победил Голиафа и так далее. У многих программистов выработалась настоящая племенная верность по отношении к нему. Добавление ко всему приставки «веб-» мгновенно делает это модным. Выскажите мнение, что Macromedia Flash хорош — и у вас могут отобрать удостоверение гика.
Но времена изменились. Веб так разжирел, что называть его открытым практически бессмысленно: у вас нет шансов внедрять HTML5, если в кармане отсутствуют несколько миллиардов долларов, которые вы хотите спустить. Консорциум W3C не прислушался к запросам пользователей и теперь стал ненужным, так что если вы не работаете в Google или Microsoft, то не можете как-то влиять на техническое развитие веба. Некоторые из ранее закрытых конкурирующих платформ теперь открылись. А экосистема JavaScript взрывается под весом своего собственного бессмысленного намолота.
Время вернуться назад к чистой доске. А теперь возьмите выпить и прочитайте следующую статью в серии: что последует за вебом?