понедельник, 7 января 2013 г.

Интересный случай с SSRF.


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

“Взломай меня полностью”



В качестве базы, для тех, кто не в курсе что есть SSRF атака, рекомендую к прочтению: http://andrepetukhov.wordpress.com/2012/11/09/%D1%82%D0%B5%D1%80%D0%BC%D0%B8%D0%BD%D1%8B-xxe-ssrf-%D0%B8-%D0%B2%D1%81%D0%B5-%D0%B2%D1%81%D0%B5-%D0%B2%D1%81%D0%B5/

Для остальных и коротко: SSRF - Server-Side-Request-Forgery. Суть: атака, в результате который мы можем инициировать запросы с атакуемого хоста
B на другие компоненты системы, например на хост C. При этом у нас нет прямой возможности послать такой запрос на хост C. Например хост C в локальной сети/DMZ. Таким вот образом мы можем делать разные интересные вещи. В некоторых интересных вариантах, хост C может быть тем же хостом B, только локальный сетевой интерфейс не доступный из Интернетов (то есть атакующему).  

В данном посте я хочу рассказать о другом интересном случае проведения SSRF атаки. А хотя нет! Давайте интерактивно, я вам опишу систему, а вы сами проведете атаку в комментах! Победителю вышлю-вручу приз - резиновую уточку 8)




//Ответы от Андрея Петухова, Владимира Воронцова и Сашу Штукера не принимаются =)

Дано:


Имеется сеть сервисов, но нам будет интересен один только.
S1: Сервер с персональными данными. Его надо “хакнуть”. Авторизация - Single Sign-On.

Host: s1.domain.com
//Уязвимость 1 - open-redirect - https://s1.domain.com/?url=http://ya.ru


Конечно есть сервер SSO.SSO: Сервер авторизации.
Host: sso.domain.com

//Уязвимсть 2 - redirect:   https://sso.domain.com/?afterauth=http://s1.domain.com
//редирект работает только в для родного домена и списка сервисов!


Документация:
Сервис проходит авторизацию по REST API.


1. Аутентифкация. Начало.

1.1. Сервис S1 проверяет куку ‘code’. Если она не пуста, то готу 2.

1.2. Сервис делает редирект на сервис SSO: https://sso.domain.com/getAuth?ID=S1
1.3.  SSO проверяет PHPSESSIONID, если для данной сессии есть аутентифкационные данные, то делает обратный редирект по параметру ID=S1: https://s1.domain.com/authDone?code=0cc1166f5a3012a1bc3eafff018acb31, где code берется из данных сессии по соотвествующему ID. Если code там нет, то готу 1.7
Если аутентификации по сессии нет, то готу 1.6
1.4. S1 ставит куку code из параметра code.

1.5. готу 1.1

1.6. Сервер SSO просит ввести логин и проль поп-апом. Стандартная аутентификация в POST запросе на SSO, пример приводить не буду. Стандартно все. Если логин (don_huan например) и пароль верный, то для данная сессия считается аутентифицированной. Если нет, готу 2.6. (капча, csrf токены есть, если что)

1.7. Регистрируется код, записывается в сессию, проверяется что существует такой ID. Если что не так - ошибка.
1.8 готу 1.3

2. Аутентификация - проверка.
2.1. Берется <code> из куки как есть и генерируется REST API запрос c сервера S1 на SSO (не видим пользователю), URL которого подписывается собственным секретным ключом сервера S1:

GET https://sso.domain.com/api/check/<code> HTTP/1.1

Header-Signature: ashJiTfV537Gfcf64f8hg4FgDkkkA785F5g/hjkR4Ed==
Header-ID: S1
Header-Data: “https://sso.domain.com/api/check/<code>”

2.3. Сервер
SSO проверяет подпись используя зарегистрированный открытый ключ S1. Проверяет подпись Header-Signature для Header-Data, есличто не так - ошибка, если все верно, то дальше.
2.4. Скрипт обработчик на SSO (/api/check/) проверяет что <code> зарегистрирован, если нет - то ошибка, иначе дальше.
2.5. Возвращается JSON :

{registered_user:”don_huan”}

2.6 Сервер S1 считывает JSON ответ, и выдает пользователю его персональные данные по registered_user. Ну или ошибку, если нет такого пользователя.


--------

Как-то так. В принципе атака очевидна, но... какой эффект! Если есть вопросы - пишите в комментах, я отвечу 8) Варианты то же пишите. Напоминаю, что это был реальный случай, реальной атаки, а не просто теор-выкладка. Так же, после нахождения ответа интересно послушать то, как это можно классифицировать и какие были уязвимости? Кстати, это пример уязвимости, которую я нашел тупо чтением документации 8) P.S. Все совпадения случайны. На самом деле там использовался OAuth, но мне лень было описывать алгоритмы OAuth таким макаром, поэтому я все cильно упростил в данной документации и архитектуре - тем проще ;)


UPD

Задачу решил без проблем i Sciurus.
Эксплойт: 
3.1 Omisión de la autenticación
https://s1.domain.com/authDone?code=../../?afterauth=http://s1.domain.com%3Furl=http://my.domain/get_any_json

Вот такая интересная, а главное простая и мощная SSRF атака. В чем ошибка?

1. Работа по GET запросу в REST API
---> Ну и что? Все запросы подписаны! Никто в этот API сунуться не сможет, он закрыт для Интернетов и открыт только для легитимных сервисов только.
2. Не фильтруется значение токена: ></../?= и тд
---> А зачем его фильтровать? Какая уязвимость тут? токен "*&%<xss.>\'SQL111" - просто вернет ошибку {error:'not found'}. Нет вектора.  
3. Redirect/OpenRedirect
---> низкий приоритет, атака клиент-сайд.
4. S1 обрабатывает редиректы HTTP, что позволяет его перекинуть на другой хост.
---> Так редирект с SSO, который злоумышленник не контролирует

Вот так все по отдельности низкопробные баги, и даже совсем не уязвимости(кроме редиректа),  а функциональные мелочи. Но вот все вместе - атака, с хорошим, таким, ущербом. SSRF тут вообще без XXE/RFI как и  говорил Андрей и без всяких враперов Владимира  (ц аолоди етсь шикарная дока, где эта тема раскрывается не только вертикально, но и горизонтально, что делает её крайне полезной, рекомендую -  https://docs.google.com/document/d/1v1TkWZtrhzRLy0bYXBcdLUedXGb9njTNIJXa3u9akHM/edit# 
). Более того, изначально запрос вообще подписан!  И третье, непосредственно выполняя атаку, нельзя поменять целевой хост (это стало возможным только с помощью двух redirect'ов). 

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

  1. don_huan передал мне буквально следующее:
    ======

    1. Sesión de fijación
    https://s1.domain.com/authDone?code=

    2. Omisión de la autenticación
    https://sso.domain.com/?afterauth=https://s1.domain.com/%3Furl=http://my.domain

    3. Solicitud falsificación
    https://s1.domain.com/authDone?code=%0D%0A%0D%0AGET%20whatever

    3.1 Omisión de la autenticación
    https://s1.domain.com/authDone?code=../../?afterauth=http://s1.domain.com%3Furl=http://my.domain/get_any_json

    ======
    Конец цитаты

    ОтветитьУдалить
    Ответы
    1. Да. Шаг 3 только лишний =). Как вообщем и 2 ;) Приватом адрес свой скинь, куда утку слать....

      Удалить
    2. Тут, вроде бы, три разных атаки:
      1. Нет проверки state (CSRF)
      2. Нет проверки redirect_uri (code stealing)
      3. Упомянутая
      Хотя я-то в этом ни черта не понимаю, только don_huan мог увидеть баги быстрее, чем @homakov.

      Удалить
  2. >Так же, после нахождения ответа интересно послушать то, как это можно классифицировать и какие были уязвимости?

    На мой взгляд, это можно рассматривать так. Code - токен, аутентифицирующий запросы пользователей. Раз так, к нему в частности и к схеме проверки подлинности в общем, применимы требования к схемам и протоколам аутентификации.
    В нашем случае нарушается требование по безопасной передаче токена между сторонами. Т.е. уязвимость - Insufficient Authentication. Уязвимость, как верно было подмечено, является следствием нескольких недостатков, главным среди которых (т.н. enabling feature) является open redirect, позволяющий реализовать утечку токена.
    Кмк, как-то так )

    ОтветитьУдалить
    Ответы
    1. Insufficient Authentication - хмм. А что такое уязвимость? В данном случае это свойство системы (из двух серверов),а не компонентов(ПО) в отдельности. Где нибудь есть описание или классификация таких штук? Как считать CVSS2 - по каждой 'фиче' отдельно? Дык там все не критично и в политику укладывается 8)

      P.S. Кстати, этот пример иллюстрирует тот факт, что PenTest отличается от Vuln-Menagment 8) По "менеджменту" уязвимостей серьезных нет..

      Удалить
    2. >В данном случае это свойство системы (из двух серверов),а не компонентов(ПО) в отдельности.

      Конечно. Это уязвимость реализации схемы проверки подлинности.

      >Где нибудь есть описание или классификация таких штук?

      Есть прекрасная статья на тему того, почему _полезную_ классификацию уязвимостей построить нельзя: A critical analysis of vulnerability taxonomies (можно построить только слишком общую, негранулярную, классификацию).
      Очевидно, что очень сложно классифицировать неатомарные концепты, а уязвимость - неатомарный в общем случае концепт, так как состоит из N недостатков (как у тебя в примере). Потому CWE и классифицирует именно недостатки - атомарные сущности.

      >Как считать CVSS2 - по каждой 'фиче' отдельно?

      На мой взгляд, все метрики уязвимостей примерно одинаково необъективны )
      Т.е. смысл метрик в итоге какой? Приоритезировать процесс устранения. Для этого в целом подходит либо словесное описание уязвимости, сложности ее эксплуатации и реализуемость схем монетизации через нее, либо готовый приоритет на исправление по мнению эксперта (я всегда выбираю второе).

      >Кстати, этот пример иллюстрирует тот факт, что PenTest отличается от Vuln-Menagment

      Ммммм... Head shot терминами! Я под ними, кажется, понимаю совсем другое!

      Удалить
    3. >В данном случае это свойство системы (из двух серверов),а не компонентов(ПО) в отдельности.

      Конечно. Это уязвимость реализации схемы проверки подлинности.

      >Где нибудь есть описание или классификация таких штук?

      Есть прекрасная статья на тему того, почему _полезную_ классификацию уязвимостей построить нельзя: A critical analysis of vulnerability taxonomies (можно построить только слишком общую, негранулярную, классификацию).
      Очевидно, что очень сложно классифицировать неатомарные концепты, а уязвимость - неатомарный в общем случае концепт, так как состоит из N недостатков (как у тебя в примере). Потому CWE и классифицирует именно недостатки - атомарные сущности.

      >Как считать CVSS2 - по каждой 'фиче' отдельно?

      На мой взгляд, все метрики уязвимостей примерно одинаково необъективны )
      Т.е. смысл метрик в итоге какой? Приоритезировать процесс устранения. Для этого в целом подходит либо словесное описание уязвимости, сложности ее эксплуатации и реализуемость схем монетизации через нее, либо готовый приоритет на исправление по мнению эксперта (я всегда выбираю второе).

      >Кстати, этот пример иллюстрирует тот факт, что PenTest отличается от Vuln-Menagment

      Ммммм... Head shot терминами! Я под ними, кажется, понимаю совсем другое!

      Удалить
  3. english dude! i want a chance to win a rubber duck too!

    ОтветитьУдалить
    Ответы
    1. Sorry, too late. We already have a winner (from first comment). Next time!

      Удалить
  4. Парни, извините, вызываете юмор. Реально. Пусть с ним с ЫЫКА, пусть будет, всем хочется. НО!

    Любому человеку который занимается не поиском, а более менее прикладным использованием уязвимостей совершенно прозрачно, что из комбинации нескольких недочетов (weakness которые) и вектора атаки (а соответственно и промежуточных результатов) может возникнуть совсем-совсем другой vulnerability из который вырастет этакий себе impact, который и надо обратить в $ путем, например, показа заказчику (ну или более прямолинейным profit!).
    Причем этот impact у системы может быть совсем другой чем у компонентов. И вполне для него считается и CVSS и другая метрика риска, но понятно, что не путем сложения исходных значений.
    И примеров подобного я могу привести стописот из разных областей, не только appsec.

    Кстати, на Zeronights 2011 была офигенная преза на тему ЫЫКА. Или это не оно? :)

    http://www.slideshare.net/DefconRussia/denis-baranov-root-via-xss-10430099

    ОтветитьУдалить
    Ответы
    1. Никто не спорит. Это как бы для закрепления и эффекта "да, тру, гребаные теоретики нее пройдут!". Примеров больше чем 100500, этот просто на тему SSRF, что нынче новомодно, к тому же просто прикольный кейс, без XXE.

      P.S. Насколько я понимаю, у Дениса был сценарий с участием админа, то есть то было СЫКА а не ЫЫКА.

      Удалить
    2. Этот комментарий был удален автором.

      Удалить
  5. я ж не только вроперы продвигаю!

    даже наоборот, именно server-side редиректы. с их помощью на статусах 307 и типа того можно оригинальные POST данные себе передавать. в доку добавил уже давно это.

    ОтветитьУдалить
    Ответы
    1. Не хотел обидеть. Да, я уже прочитал дока становится все лучше и лучше 8)

      Удалить