воскресенье, 21 января 2007 г.

OpenID & phishing

Если вы не в курсе, спецификация OpenID версии 2.0 уже в финальной стадии. Учитывая усиливающийся buzz, касающийся OpenID, мы скоро увидим очень много мест, где эту валюту принимают (я сам тоже собираюсь приложить к этому руку :).
Если вы не в курсе о чем речь, то дальнейшее будет довольно сложно понять :)

В связи с этим уже возникают некоторые опасения. Ben Laurie описал простой сценарий, при котором ваши login/пароль к OpenID-провайдеру (OP), например, LiveJournal, могут стать легкой добычей фишеров всех мастей, если не проявлять осторожность. В общих чертах, сценарий такой:
  1. Вы заходите на милый безобидный сайт, хостящий трогательные фотки кошечек. Единственное, что просит от вас сайт, когда вы хотите оставить какое-либо критическое замечание под тронувшим вас произведением - это зарегистрироваться, чтобы избежать спама. При этом (как мило с их стороны) процесс регистрации может быть пропущен, если вы аутентифицируете себя по OpenID. Само собой, зачем вам оставлять где попало свой email, да и пароль придумывать, если за вас может поручиться какой-либо OpenID-провайдер? Выбирате OpenID, пишете туда, например, mderk.livejournal.com, и отправляете форму.
  2. Теперь вас должны отправить на http://www.livejournal.com/openid/server.bml . Если вы уже аутентифицированы в ЖЖ, то он сразу отправит вас обратно, снабдив дополнительными параметрами в URL, которые подтвердят запрашивающему сайту, что вы действительно тот, кем представляетесь. Если же нет - LiveJournal попросит вас прежде ввести login/пароль. Это в теории. На практике, "кошечный" сайт может оказаться не таким милым, и вместо OP endpoint может отправить вас на свой прокси, замаскировав url соотвествующим образом, например http://www.livejournal.com/openid/server.bml?lot_of_junk@evilcats.example.com. Вы увидите перед собой ту же страницу с LJ, на которой нужно ввести свои данные, только показана она будет через прокси evilcats.example.com и login/пароль к LJ прежде чем попасть куда надо, останутся в логах прокси. Что дальше - понятно. All your base belongs to us.

Как бороться, если не перепроверять каждый раз URL, куда нас послала black-hat Relying Party? Вопрос пока еще не решен. Разработчики OpenID оставляют этот вопрос за пределами протокола.
Одно из решений - использовать для OpenID-аутентификации специальный софт. Например, в Firefox3 собираются встроить поддержку OpenID. Вместе с этим они бы могли встроить средство для whitelisting тех OP endpoints, которые имеют для нас смысл (либо некий менеджер идентификаторов, жестко сопоставляющий наши openid-идентификаторы с OP endpoints). Того же эффекта можно было бы достигнуть при помощи специального расширения/тулбара. Но это, как понимаете, решение далеко не универсальное, как все решения, требующие установку дополнительного софта.
Идеальным было бы решение server-side. Мысли такие:
  1. OP endpoint должен всегда использовать HTTPS, причем сертификат должен быть выдан общеизвестным CA. С одной стороны, можно всегда проверить сертификат, с другой стороны это отсекает low-end фишеров, которые не озаботились получением своего "честного" сертификата. Решение все же не идеально, т.к. предполагает, что
    1. человек хоть как-то осведомлен о назначении сертификатов, и не будет закрывать предупреждения о нарушении политики безопасности SSL, если ему приедет серт, подписанный Snake Oil Corporation;
    2. человек обратит внимание, что страница открыта в не-SSL-режиме, если вражеский прокси отправит её ему в plain text
    3. фишер не оказался настолько крут, что приобрел себе сертификат, и никаких сообщений о нарушении безопасности при открытии страницы не последовало.
    Так что решение - так себе. Хотя то, что авторизация должна происходить только в SSL-mode, не отменяется.
  2. OP endpoint должен использовать какую-либо другую схему подтверждения того, что человек зашел на него непосредственно, а не через подстроенную под него страницу.

По второму пункту мне есть что сказать. Я вижу такой способ:
OP должен осуществлять авторизацию только при наличии у клиента специальной cookie, которая разрешает авторизовывать его по OpenID. Причем secure-only-cookie. Некий случайный мусор, хешированный SHA, и отраженный в списке выданных cookies на сервере OP. Тут возникает проблема. С одной стороны, бесполезно привязывать эту cookie к идентификатору пользователя на сервере, т.к. идентифицировать по ней было бы дырой в безопасности. Но тогда злой прокси может сам себе выписать cookie, и дурить сервер OP, предлагая ему эту cookie, якобы пришедшую из браузера пользователя. Так что привязка должна быть. Она не влечет за собой автоматической авторизации, но позволяет отследить то, как эта cookie была использована впоследствие.

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

У данной схемы есть недостатки. Первый заключается в том, что браузером мог легально воспользоваться один пользователь, а потом также легально по OpenID хочет авторизоваться другой, либо виртуал первого. В этом случае первый может быть по нашему сценарию несправедливо забанен. Второй недостаток в том, что если cookie не установлена, то OP должен сказать клиенту, что надо зайти на определенную страницу, чтобы ее получить. А вот тут уже опять открывается пространство для social engineering со стороны фишеров, т.к. cookie может быть получена только авторизованным пользователем. Что делать, чтобы избежать второго витка той же проблемы, пока что не придумал.

От тех кто дочитал до сего момента, очень интересно было бы услышать предложения и замечания :)

Также в тему:
http://simonwillison.net/2007/Jan/19/phishing/
http://usablesecurity.com/2007/01/20/phishing-and-openid/

10 комментариев:

  1. Асимметричное шифрование. На стороне клиента информация шифруется открытым ключом, сервер для дешифрации использует закрытый ключ. Под информацией подразумевается логин+пароль+адрес сайта для которого производится авторизация(или случайный мусор/ключ для этого запроса)
    . В случае если пользователь уже залогинен, шифруется пользовательская кука+адрес сайта(или случайный мусор/ключ для этого запроса).

    ОтветитьУдалить
  2. Некий менеджер идентификаторов... где-то я это уже видел... :-P

    А можно мне вторую часть данного опуса перевести на аглицкий и опубликовать у себя?

    ОтветитьУдалить
  3. Дмитрий, да, можно.
    С удовольствием читаю ваш блог по этой теме :)

    ОтветитьУдалить
  4. [...] In the meantime, here’s a brief summary of Maxim Derkachev’s suggested solution to the OpenID phishing problem: [...]

    ОтветитьУдалить
  5. @3BEP
    Это подразумевает, что у клиента стоит какое-то client-side приложение или плагин, который поддерживает такой протокол. В таком случае есть решения и попроще...

    ОтветитьУдалить
  6. [...] Идею, описанную во вчерашнем посте, подхватил Дмитрий Шехтман. Он значительно упростил ее, также добавив некоторые аспекты, о которых я до этого не подумал. Разберу его замечания, и добавлю кое-что от себя. Итак, его резюме всей идеи: [...]

    ОтветитьУдалить
  7. Подразумевалось, что открытый ключ передается вместе с формой, шифрование производится ява-скриптом.

    ОтветитьУдалить
  8. 3BEP, дырка в том, что пользователю подсовывается поддельная форма, а от этого может спасти только отдельный софт. думаю openID сообществу стоит задуматься над разработкой специальных плагинов к браузерам.

    ОтветитьУдалить
  9. Думаю от прокси будет значительно проще избавиться - ОР перед индентификацией пользователя заставляет браузер перейти именно на ОР (window.location = "http://www.livejournal.com/openid/server.bml".

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

    ОтветитьУдалить

Постоянные читатели