Я провожу семинар, который я часто провожу в частном порядке для организаций или в рамках различных конференций, которые я называю «Hack Yourself First». Я писал о том, что я делаю в последнее время в связи с моими предстоящими семинарами в США в следующем месяце, и о тех, которые я буду проводить в Лондоне в январе, но вкратце, это пара дней очень практических упражнений, на которых мы смотрим на куча различных аспектов безопасности таким образом, чтобы действительно резонировать с разработчиками. Я сделал очень сжатую версию этого на мероприятии DDD в Мельбурне на выходных, и был результат, которым я поделился. Это интересная иллюстрация риска и пример того, как вовлеченная организация справилась с ним.
Одно из упражнений, которые я выполняю (и то, на чем мы сосредоточились в DDD), заключается в изучении взаимодействия мобильных приложений в Интернете. Мы рассмотрим, как перехватывать трафик (как HTTP, так и HTTPS), используя Fiddler (мы используем Чарльза для людей Mac), и выявляем общие анти-паттерны безопасности в том, как приложения взаимодействуют с API. Участники делают это на своих собственных устройствах и используют свои обычные приложения, установленные на устройстве; они просто используют их так, как им предназначено, и просто следят за движением. Часто встречаются довольно интересные вещи, и эта сессия не разочаровала.
Один из ребят открыл приложение realestate.com.au , которое является одним из наших ведущих сервисов по аренде и продаже недвижимости здесь, в Австралии. Вот как это выглядит:
Вы можете заметить, что это на Android — подробнее о значении этого в ближайшее время. В любом случае, он вводит имя пользователя и пароль, нажимает кнопку «Войти» и видит это в Fiddler:
Он сразу заметил, что первый запрос к / login / session был отправлен через HTTP или, другими словами, незашифрованное соединение. Вот сам запрос:
POST http://www.realestate.com.au/login/session HTTP/1.1
Content-Type: application/json; charset=utf-8
Content-Length: 46
Host: www.realestate.com.au
Connection: Keep-Alive
Accept-Encoding: gzip
Cookie: reauid=1b834768611900008756c5557abb0b00636d0000
User-Agent: okhttp/2.2.0
{"email":"[email protected]","password":"aaaaa"}
Вот и все — учетные данные отправляются через незашифрованное соединение! На самом деле, это то, что происходит в первом запросе в этой трассировке Fiddler выше. Этот запрос приводит к 301 «постоянному перенаправлению», которое затем заставляет клиента отправлять кредиты в безопасную схему в третьем запросе (второй является туннелем HTTP CONNECT ). Учетная запись недействительна, следовательно, ответ 400, но дело в том, что в первую очередь они небезопасно вышли через провод.
Но вот что мне показалось наиболее интересным и достойным того, чтобы о нем написать — тогда я попытался сделать то же самое со своего iPhone, где приложение выглядит так:
Очевидно, что это другое приложение, работающее на iOS, а не на droid, но очевидно, что оно имеет ту же цель. Вот что происходит, когда вы пытаетесь войти с iOS:
Первый запрос — аналитика Omniture (теперь часть Adobe), что не является чем-то необычным. Затем он создает туннель, после которого интересным является запрос к / login / session, который выглядит следующим образом:
POST https://www.realestate.com.au/login/session HTTP/1.1
Host: www.realestate.com.au
Content-Type: application/json
X-NewRelic-ID: UAQDUF9WGwsAVFBQDgY=
Cookie: mid=8145197813623482640; reauid=55b107ca49590000e890c655010d0500f68d0300
Connection: keep-alive
Proxy-Connection: keep-alive
Accept: application/json
User-Agent: realestate.com.au/2.11.0 (iPhone; iOS 8.4; Scale/3.00)
Accept-Language: en;q=1
Accept-Encoding: gzip, deflate
Content-Length: 46
{"email":"[email protected]","password":"aaaaa"}
На случай, если еще не очевидно, какое значение имеет этот запрос по сравнению с запросом Android, давайте разберемся с двумя:
По умолчанию приложение для iOS с самого начала выходит за пределы HTTPS по сравнению с приложением для Android, которое начинает небезопасно общаться, а затем перенаправляет на защищенную схему. Это точно тот же запрашиваемый ресурс, но по умолчанию он не защищен приложением Android.
Позвольте мне быстро уточнить, почему я могу видеть трафик, отправляемый по HTTPS в этом запросе iOS: мой iPhone был настроен на использование Fiddler в качестве прокси-сервера, что означало, что все HTTP / S-запросы проходят через него. Теперь при нормальных обстоятельствах такой прокси-сервер (который фактически является человеком посередине) не может видеть содержимое HTTPS-трафика, и именно поэтому у нас в первую очередь SSL. Однако, если вы устанавливаете корневой сертификат Fiddler на устройстве, как описано в этой ссылке, Fiddler теперь может перемещаться назад и вперед с сервером, используя законный сертификат, а также назад и вперед с устройством, используя свой собственный самозаверяющий сертификат, который устройство теперь доверяет из-за установленного корневого сертификата, Вышеприведенный запрос от iOS является безопасным, но это не значит, что я не могу перехватить, прочитать и манипулировать им, когда я также управляю устройством. Это само по себе является серьезным наблюдением, которое часто приходит как новость для разработчиков.
Вот почему я считаю, что ситуация с приложениями для Android значительна: сделать ошибку очень легко. Буквально один символ отсутствует в чьем-то конфигурационном файле для приложения Android, и это делает разницу между наличием сильно зашифрованного соединения между устройством и сервером и нулевым шифрованием вообще при первом запросе. Тот факт, что страница входа в систему просто перенаправляет небезопасный запрос, затем скрывает неверную конфигурацию, но это понятный шаблон, потому что это то, что мы обычно делаем, когда хотим применить HTTPS на веб-сайте — мы применяем безопасную схему, если к ней обращаются через HTTP.
Есть много вещей, которые можно сделать, чтобы значительно снизить риск того, как что-то подобное может пробиться в дикую природу:
- Не поддерживайте небезопасную схему запросов POST к конфиденциальным ресурсам. Это можно было бы легко предотвратить на стороне сервера, просто не перенаправляя запрос. Выявление того, что конфиденциальный ресурс, такой как логин, должен вызываться только надежно и сразу же вызывать сбой, если это не вызвало бы возникновение этой проблемы гораздо раньше. Ранний сбой — разработчик быстро выяснит, почему их запрос не работает во время сборки.
- Блокируйте API-интерфейсы точно так, как вы ожидаете их вызова. Ссылки на API-интерфейсы закодированы в приложениях-потребителях, поэтому вам не нужно заботиться о том, чтобы пользователь вводил http: //… или браузер по умолчанию использовал схему HTTP. Фактически, я бы сделал еще один шаг и даже разместил эти API в своем собственном домене (или поддомене). Затем вы можете отключить HTTP-схему для всего этого, а также получить некоторые другие преимущества с точки зрения того, как вы можете настраивать и масштабировать API независимо от сопутствующего веб-сайта.
- Всегда прокси свои приложения и смотреть на трафик. Одному парню понадобилось несколько минут, чтобы выявить эту проблему, просто зная схему поиска. Для таких рисков гораздо проще быть скрытыми за богатыми клиентскими приложениями, потому что нет такой же видимости запросов, как в браузере, где вы можете легко увидеть их в URL или инструментах разработки.
Но я также хочу отдать должное REA Group, которая управляет realestate.com.au. Я отправил подробности об этом по электронной почте контактному лицу, которое у меня есть в группе безопасности в воскресенье утром, и через семь минут я получил ответ . В воскресенье! Уже на следующий день они исправили проблему и обновили приложение в магазине Google Play. Я также сказал им, что собираюсь написать это, как только проблема будет решена, и они были абсолютно в порядке с этим. Подобный вопрос настолько легко внедрить в производство, что решение этой проблемы — настоящее испытание организации, ИМХО.
Так что проверяйте ваши приложения, в большинстве случаев, когда я провожу эти семинары, люди находят что-то похожее, просто потому, что так легко ошибиться. Опять же, вам или кому-либо еще легко найти эти ошибки!