Угнать за 9 символов

    Сегодня я расскажу вам историю об уязвимости, которая существовала в одном интернет-банке много лет. Её эксплуатация была настолько элементарной, а опасность была настолько не очевидна, что ни кто так и не обратил на неё внимание.

    С этим банком у меня была договорённость о поиске уязвимостей и все мои действия были санкционированными. В тот вечер я уже потратил приличное время на поиск более-менее критичной уязвимости и так не найдя ничего стоящего, было уже отчаялся. Но тут мой взгляд зацепился за один параметр в череде запросов к серверу в момент авторизации. К слову, этот банк использовал передовую и очень надежную технологию авторизации, а именно двухфакторную авторизацию через смс. Так вот, параметр GET запроса, на который я обратил внимание, имел вид: go=/path/to/some/page
    и формировался на стороне сервера для дальнейшей переадресации. Но проблемой было то, что путь для переадресации был относительным и добавлялся к домену сайта и поэтому я игнорировал этот запрос в своих предыдущих исследованиях. К тому же, что бы в нем существовала потенциальная уязвимость, должен был иметь место ряд факторов, а именно:
    1). возможность при помощи значения параметра go
    обеспечить переадресацию на сторонний домен
    2). возможность на клиенте задавать значение этого параметра
    3). и наконец, после авторизации при редиректе на сторонний домен должна передаться какая нибудь ценная информация

    В итоге, с малой надеждой на какой либо результат, я начал искать пути эксплуатации потенциальной уязвимости.

    Немного поразмыслив, я нашел решение первой из трёх вышеперечисленных задач. Предлагаю читателю тоже подумать над этой задачкой. У нас есть, на первый взгляд, относительный путь /path/to/some/page,
    который добавляется к домену сайта internet-bank.com
    и в итоге получается адрес internet-bank.com/path/to/some/page.
    Как нам сформировать урл со сторонним доменом? Кто догадался, может поставить себе плюсик за сообразительность. Кто хочет узнать ответ, читает дальше. Так вот, если мы вместо /path/to/some/page
    добавим .some.domain.com,
    то получится ссылка для переадресации вида internet-bank.com.some.domain.com


    Таким образом, первый пункт из трёх перечисленных выше выполнен, мы сформировали имя стороннего домена, на который есть потенциальная возможность перенаправить пользователя. Осталось ещё 2 пункта.

    Для выполнения пункта 2 я попробовал авторизоваться в интернет-банк не с адреса internet-bank.com,
    а с internet-bank.com?go=/path/to/some/page.
    И о чудо, сервер произвел двухфакторную авторизацию и в итоге перенаправил меня сперва на адрес internet-bank.com/path/to/some/page/?token=37C853F2CA868D819BD9514C3CCEB,
    а потом на internet-bank.com/path/to/some/page.
    Мне осталось разлогиниться и авторизовать с адреса
    internet-bank.com?go=.some.domain.com.
    Сделав это, меня перекинуло на адрес internet-bank.com.some.domain.com?token=37C853F2CA868D819BD9514C3CCEB, таким образом пункт 3 выполнился автоматически. Зачем данный токен использовался в редиректах при авторизации, я так и не понял, но в итоге я имел возможность по ссылке internet-bank.com?token=37C853F2CA868D819BD9514C3CCEB
    авторизоваться с любого компьютера без ввода логина, пароля и смс.

    Mission completed.

    А что дальше? А дальше регистрируем домен второго уровня, например como.wtf, распространяем в Интернете ссылку internet-bank.com?go=o.wtf
    и получаем доступ к чужим аккаунтам в интернет-банке благодаря пересылке авторизационных токенов на internet-bank.como.wtf


    В итоге получается, что для того, что бы иметь возможность угнать чужой аккаунт, нам достаточно добавить к совершенно безопасному адресу сайта интернет-банка всего 9 символов зловредного кода: "?go=o.wtf"

    А для себя я сделал следующий вывод: если есть хоть малейшая вероятность существования потенциальной уязвимости, её нужно устранять.
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 25

      +7
      Всегда надеялся, что в таких системах токен привязан к IP, например, чтобы в случае перехвата токена сложнее было им воспользоваться.
        +6
        Как оказалось, привязки не было ни какой. Единственное, что было, так это то, что токен одноразовый. Но это ни как не спасало.
          0
          Весьма бесполезно, IP меняются — может и юзеру создать неудобства.
            0
            Вовсе нет. Как пишет автор, токен одноразовый, так что он будет использоваться единовременно при авторизации.

            Авторизация, как опять же пишет автор, здесь двухфакторная. Для защиты по IP нам надо будет на первом этапе записать IP пользователя, а на втором проверять.

            Всё это будет длиться секунд 20. Максимум 3-5 минут, если смс задержалась. Маловероятно, что ваш IP сменится за столь короткий промежуток времени.
              0
              Ну хм может пригодиться но лучше кодить сразу с правильной валидацией редиректа, тогда вариантов потерять токен по пути значительно меньше.
                0
                Маловероятно, что ваш IP сменится за столь короткий промежуток времени.
                Юзер может быть за шлюзом с балансировкой нагрузки на разные каналы. И это необязательно что-то особенное, у меня одно время был домашний роутер с ADSL и ethernet линками одновременно.
                Юзер можеть выходить в Сеть через мобильный и-нет и скакать между базовыми станциями, непредсказуемо меняя свой внешний IP.
                Юзер может сидеть через Tor.
              0
              Даже, если токен будет привязан к IP, то получивший его сервер internet-bank.como.wtf может отдать пользователю javascript, который выполнит необходимые действия от токена и с IP пользователя. Такому сценарию может помешать CSRF-токен, но и его реализация не всегда идеальна.
              +1
              Пять баллов!
                +2
                Кошмар! Разве можно токен отдавать?
                  +6
                  Да кто читает эти RFC, хосспадя.
                  +1
                  Очень круто!
                    0
                    что ни кто так и не обратил на неё внимание.

                    Так и не обратил — в смысле баг не пофиксили до сих пор?
                      0
                      Пофиксили после того, как я его зарепортил
                        0
                        Вознаграждение хоть в итоге получили ?! Баг то серьёзный на самом то деле!
                          +1
                          В процессе выплаты
                      +5
                      Как нам сформировать урл со сторонним доменом? Кто догадался, может поставить себе плюсик за сообразительность

                      Думаю, многие, как и я, подумали о собаке @
                      Но ваш вариант с поддоменом, особенно с вхождением в него зоны домена банка, действительно позволяет замаскировать урл под благонадежный.
                        0
                        Еще вариант — если на сайте есть скрипт внешнего редиректа, то можно использовать его.
                        • UFO just landed and posted this here
                            +1
                            При относительном пути можно было бы воспользоваться ссылкой без указания uri-схемы ?go=//evil.host/
                            https://tools.ietf.org/html/rfc3986#section-4.2
                              +1
                              А по какому RFC допускаются относительные пути в Location при 301/302?
                                +1
                                Да, можно передать все как есть в Location…
                                … и получить возможность указания злоумышленником произвольных заголовков ответа путем передачи символа перевода строки в url-параметре :)
                                • UFO just landed and posted this here
                            +6
                            Прикольно, ключевой баг в том что банк вообще не валидировал параметр «go». Там наверно и header injection можно было откопать.
                            С Гитхабом очень похожая история была, тоже угон токена и последующий вход (http://habrahabr.ru/post/211845/)
                              +2
                              Раньше писать про то, как складывать пути на дисках.
                              Для .NET на все собеседования выносили вопросы ответом на которые должны были стать варианции по применению System.IO.Path.Combine(...)

                              Теперь, имеем полноценного приемника System.Uri

                                  class Program
                                  {
                                      static void Main(string[] args)
                                      {
                                          var domain = new Uri("https://internet-banking.com", UriKind.Absolute);
                                          var path = ".subdomain.tw";
                              
                                          var uri = new Uri(domain, path);
                              
                                          Console.WriteLine(uri);
                                      }
                                  }
                              


                              И на выходе будет то, что нужно:
                              https://internet-banking.com/.subdomain.tw
                              


                              P.S. Но Uri не самый простой инструмент, там есть свои особенности.
                                0
                                Хорошая статья)

                                Only users with full accounts can post comments. Log in, please.