Пользователь
0,0
рейтинг
13 ноября 2012 в 12:00

Разработка → Анатомия атаки: Как я взломал StackOverflow перевод

Почти два года назад я наткнулся на довольно значительную уязвимость в сети сайтов StackExchange. Я говорю «наткнулся» потому, что я не пытался взломать сайт. Обстоятельства приоткрыли мне дверь. Сама уязвимость является довольно интересной, и содержит урок для всех, кто создает и занимается поддержкой сайтов или серверной инфраструктуры. Итак, вот история о том, как я взломал StackOverflow

Исходные данные


В то время я работал в небольшой компании, где имелся фаервол с совершенно драконовскими ограничениями. Он резал все заголовки запросов и ответов, не соответствующие спецификации HTTP/1.1 (и даже резал валидные HTTP/1.1 заголовки). Это играло злую шутку с сайтами, которые полагаются на такие вещи, как X-Requested-With. Поэтому, для своих «внешних похождений», я настроил прокси.

У меня было несколько серверов в то время, так что я просто поставил на одном из них Squid. Так как я кое-что соображал, я разрешил подключения к прокси только с 127.0.0.1. Я поднял SSH туннель к серверу и указал браузеру localhost в качестве прокси. Браузер подключался к туннелю, который подключался к Squid'у на сервере. Все было отлично. Кроме того, что весь мой трафик шифровался, я получил возможность нормально пользоваться сайтами.

Для тех из вас, кто хочет мне сказать, что я поступил плохо, я хочу обратить ваше внимание на то, что у меня была возможность сделать это. И не просто возможность, мне открыто было сказано использовать прокси, так как мы должны были работать с некоторыми сайтами, которые не работали через наш фаервол. Так что я не делал ничего «неправильного».

Атака


В то время я часто бывал в чате StackOverflow. Тогда он еще только появился, и в нем была парочка багов. В один прекрасный день сайт начал показывать мне стек вызовов. Я не придал этому значения, так как часто встречался с этим по всему интернету. Вообще-то, почти каждый раз, когда я получал сообщение об ошибке на сайте, написанном на ASP.NET, я видел стек вызовов.

И тут я заметил новый пункт меню в чате. Этот новый пункт меню назывался «Admin». Чисто из любопытства, я нажал на ссылку, полагая, что мне будет отказано в доступе. То, что произошло дальше, удивило меня. Я получил полный доступ ко всему. У меня была консоль разработчика, где я мог видеть кто что делает. У меня был интерфейс для работы с базой данных, где я мог напрямую запрашивать что угодно из любой базы данных. Я получил полные админские права.

Что произошло дальше


Следующее, что я сделал — сразу сообщил об этом модератору. Через несколько минут я был в приватном чате с модератором, а также двумя разработчиками. Причина была найдена приблизительно в течение 10 минут. Еще через 10 минут проблема была решена поверхностно. На полное исправление ушла пара часов. Они отлично сработали. У меня до сих пор лежит лог того чата, и я хочу сказать, что эти разработчики заслуживают всяческих похвал. Они ответили быстро и профессионально. И решили проблему в кратчайшие сроки.

Уязвимость


Если вы сообразительны, то, скорее всего, догадались, что произошло. Так как я выходил через прокси, к моим запросам добавлялся заголовок X-Forwarded-For. Значением этого заголовка был IP с которого запрашивался прокси-сервер. Но, так как я подключался к прокси через SSH туннель, IP был локальный. Так что Squid добавил X-Forwarded-For: 127.0.0.1

Но самое интересное было то, что показывал ASP в логах. Когда они посмотрели дампы моих запросов, там красовалась запись REMOTE_ADDR: 127.0.0.1! В их приложении все проверки заголовков были реализованы правильно. Но IIS был неправильно настроен и он перезаписывал REMOTE_ADDR значением X-Forwarded-For, если тот присутствовал. И благодаря такой вот ошибке конфигурации я смог получить доступ к админке, при помощи моего прокси-сервера.

Выводы


Никогда не полагайтесь на X-Forwarded-For, как мы видим — это не безопасно. Всегда используйте REMOTE_ADDR. Здесь стоит задуматься, нужна ли вам вообще защита, основанная на IP. Или, по крайней мере, не стоит на нее полностью полагаться, а использовать лишь как дополнительную меру.

Интересно отметить, что разработчики действительно использовали надлежащую проверку заголовков. Суть в том, что вы никогда не должны слепо доверять вашей инфраструктуре. Эта дыра появилась из-за разницы конфигурации между сервером и приложением. Такие мелочи случаются каждый день. Приложение предполагает одно, а сервер — другое. Проблема в том, что такое доверие может полностью подорвать безопасность. В этом случае, разработчики доверяли значению REMOTE_ADDR (вполне обосновано), но сервер был неправильно настроен. Конечно, есть ситуации, когда вы должны доверять серверу или другим компонентам, но надо помнить о том, что слепое доверие — это не очень хорошая вещь. Подумайте об этом, и постарайтесь застраховаться от подобных случаев.

Команда StackOverflow великолепно решила этот вопрос. Быстро, отзывчиво и разумно. Они попросили меня о помощи (которую я с удовольствием предоставил), и вели себя профессионально и уважительно. Они проделали фантастическую работу. Мы все должны извлечь урок. Реагировать на сообщения о уязвимостях серьезно. Решать вопрос профессионально и быстро.

Что касается PHP


Самое интересное здесь то, что приложения, написанные на PHP, могут иметь такую же уязвимость. Смотрим Symfony2 Request class. Выглядит отлично. Пока вы не заметите, что он использует статическую переменную, чтобы определить, следует ли доверять прокси. Это означает, что если любая часть вашего приложения захочет получить заголовки от прокси (например, для записи в лог), все ваше приложение после этого будет получать загловоки именно от прокси. Чтобы увидеть, подвержен ли ваш код подобной уязвимости, поищите в нем вызов $request->trustProxy(). Также обратите внимание, что обратного механизма нет. Вы не можете «перестать доверять» прокси. Я думаю, это большой архитектурный просчет…

Zend Framework 2 поступает аналогично. Он имеет класс, который ведет себя похожим образом (в плане получения IP). Интересно, что в Zend Framework 1 способ получения IP-адреса был адекватным. Вызывающий код должен явно указывать что он хочет получить, а по-умолчанию должен быть безопасный вариант.

Заключение


Эта проблема стала результатом сочетания двух мелких просчетов. По отдельности их очень легко упустить из виду. Но если они сойдутся определенным образом, вы получите очень серьезную угрозу безопасности. И самый большой урок в том, что вы действительно не можете доверять чему-либо за пределами вашего приложения. Если вы можете обойти это (например, не доверяя заголовкам и переменным, вроде REMOTE_ADDR), то вы можете сделать ваше приложение более безопасным. Но, прежде всего, думайте о коде, который вы пишете и о системах, которые вы строите. И поддерживайте их.
Перевод: Anthony Ferrara
@truezemez
карма
93,5
рейтинг 0,0

Похожие публикации

Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (52)

  • +8
    • +2
      Да. Там есть такой пользователь. Давненько уже.
      • +4
        ДМИТРИЙ, ХОЧУ ВЫРАЗИТЬ ВАМ БЕСКОНЕЧНУЮ БЛАГОДАРНОСТЬ ЗА ВАШЕ ТВОРЧЕСТВО… ОНО НЕ ПРОСТО ПОМОГАЕТ ЧТО-ТО ПОНЯТЬ, ЧТО-ТО ПЕРЕЖИТЬ, ОНО ВДОХНОВЛЯЕТ, ОНО ИНТЕРЕСНО И Я СЧАСТЛИВА, ЧТО ЖИВУ С ВАМИ В ОДНО ВРЕМЯ! СПАСИБО ВАМ ЗА ПОТРЯСАЮЩИЙ КОНЦЕРТ В МОЕМ РОДНОМ ВОРОНЕЖЕ, КОТОРЫЙ ТРУДНО ЗАБЫТЬ… ЭТО БЫЛ ОСОБЕННЫЙ КОНЦЕРТ!))) СПАСИБО, ЧТО СДЕРЖИВАЕТЕ СЛОВА, СПАСИБО ЗА ТО, ЧТО ВЫ ПРОСТО С НАМИ...

        Ох уж эти девочки…
        • 0
          как вы определили что писала девочка?
          • +1
            … И Я СЧАСТЛИВА, ЧТО ...
            • 0
              не хочется быть занудой, но явно этот текст написан ради лулзов…
          • 0
            One of my fans ask me to put that words right here. Hi, Nadejda, it's all for you!

            Я что-то ни одного мужика ещё не видел с таким именем.
    • +4
      Гугл до сих пор выдает такой результат :)

    • 0
      И даже на гитхабе.
      • +13
        Д.МАЛИКОВ: Я даже не знаю, что это такое. Я получаю в «Твиттер» очень много подобных сообщений, но это «клон». Я бы с удовольствием, но у меня не так много талантов, к сожалению, а технического нет совсем. (источник)
        • +9
          Отмазывается :) Еще одного певца из той-же серии, общие знакомые спалили за Xcode. А девочка из когда-то популярной девочковой группы не для публики пела на эсперанто.
          • 0
            О, а можно поподробнее про эсперанто? Хорошие группы, поющие на этом языке, можно по пальцам пересчитать.
            • +1
              Что знаю — написал в личку. Я не пресса, и публично распространяться о личной жизни, пусть даже публичных людей, не считаю уместным :)
  • +26
    Команда StackOverflow великолепно решила этот вопрос. Быстро, отзывчиво и разумно… оба вели себя профессионально и уважительно. Они проделали фантастическую работу

    Запомню этот брейндамп на случай, если придется написать околоамериканский текст на какое-нибудь не очень значительное событие.
    • +10
      Это я еще сократил количество дифирамб в адрес разработчиков.
  • 0
    А этими двумя разработчиками были как раз Джоэль Сполски и Джефф Этвуд?
    • +48
      Этими двумя разработчиками были Альберт Эйнштейн
  • +43
    Забавный баг, и еще более забавный заголовок статьи: «Как я взломал StackOverflow? Зашел на него через прокси и там была кнопка админ-панели!».
    • +7
      Как я Overflow Stack…
  • +5
    Забавно, как сразу видно что это перевод.
    Вот русскоговорящие редко пишут «оба вели себя профессионально и уважительно. Они проделали фантастическую работу». Но да, перевод должен быть как можно ближе к оригиналу, а иностранцы любят эти похвалы.
    Это не недостаток ничего такого, просто особенность речи.
    • +1
      А русские как пишут? «оба вели себя адекватно. Они сделали какую-то фигню»? %)
    • +3
      Да нет, просто идиомы не переводить надо, а заменять на соответствующие в своем языке. Например, «They did a fantastic job» вполне можно перевести как «они просто молодцы», «они были на высоте», «они здорово справились».
      • 0
        Спасибо. Учту. Но автор действительно много хвалит разрабочиков и я не знаю как перевести все эти комплименты, чтобы они не выглядели слащаво. Подскажете?
        Really, they could not have responded better. I still have the chat log, and let's just say that those developers deserve every accolade that I can give them. They responded quickly and professionally. And they solved the problem within minutes of me reporting it.

        The SO team was absolutely incredible to deal with during this. They were fast, responsive and reasonable. They asked for my help (which I gladly gave), and were both professional and respectful. And not only did they do all of this, but they found and fixed the exact problem faster than I would have ever expected. I really can't talk up the developers enough. They did a fantastic job. We should all take a lesson from them.
        • +8
          Как-то так.

          Серьезно, они не могли бы справиться лучше. У меня все еще остался лог чата, и, говоря начистоту, те разработчики были выше всяческих похвал. Реакция была быстрой и профессиональной, а проблема оказалась решена в считанные минуты.

          Было очень здорово поработать с их командой поддержки, действовавшей быстро, отзывчиво и разумно. Попросив меня о помощи (а мне было приятно им помочь), они вели себя профессионально и уважительно. И самое главное, они нашли и устранили причину быстрее, чем я мог себе представить. Я не могу перестать их хвалить, они просто молодцы. Мы все должны у них учиться.

          Когда переводите, старайтесь думать на языке, на который переводите, а не с которого. Не бойтесь полностью перефразировать текст, от этого он только выиграет. Английский текст русскими словами никогда не станет русским текстом, слишком много различных устоявшихся фраз и выражений, и вообще структура речи другая. Старайтесь сперва полностью понять автора, а потом сказать его мысль так, как сказали бы вы. И не забывайте о деепричастиях. Английскому свойственны короткие предложения, а на русском их лучше заменять на сложносочиненные.

          У вас вышел неплохой перевод, я почувствовал о том, что это перевод, только к пятому абзацу :) Но всегда есть куда улучшаться.
          • 0
            Спасибо за ценные советы. На самом деле, я практически всегда перефразирую текст, но этот перевод был сделан в спешке, поэтому остался «привкус синтетики». Еще раз спасибо.
          • 0
            Сам себя еще поправлю: «could not have… better» хорошо перевести «как нельзя лучше». Они справились как нельзя лучше.
          • –1
            А что толку, все равно американским менталитетом разит на версту: «говоря начистоту» — когда Вы в последний раз видели такой оборот в непереводном тексте?
            • +1
              • 0
                «Серьёзно» в начале предложения тоже глаза режет. Особенно в паре с «говоря начистоту»
                • 0
                  Вы меня, люди, поражаете. Вы что, только мануалы и техдоки читаете?

                  www.gramota.ru/spravka/punctum/58_665 — второе значение
                  dic.academic.ru/dic.nsf/ushakov/1022754 — пятое
                  • 0
                    Да, но обычно эти слова употребляются немного по другому. Не в качестве междометия, как тут.
                    • +1
                      Во-первых, это не междометие, а вводное слово. Во-вторых, заявление совершенно безосновательное, оно употребляется как вводное слово в большом количестве литературы, в том числе классической, и никак не связанной с переводами. По ссылкам примеры.

                      Если вы лично обычно не используете какой-то оборот речи, это не является основанием для таких спорных утверждений.
            • 0
              «Если честно», «честно говоря»…
          • +1
            >Серьезно, они не могли бы справиться лучше.
            я бы и по этой фразе сразу бы заподозрил перевод :)
            • 0
              «Серьезно, они справились как нельзя лучше». Я там выше поправился.
        • +2
          Кстати, «and were both professional and respectful» — это не «оба были профессиональными и уважительными», а «были одновременно профессиональными и уважительными». Первый случай звучал бы как «and both were».
          • +1
            держались корректно и профессионально
            • +1
              Я понимаю, что лучше сформулировать иначе, я сам выше написал это как «вели себя профессионально и уважительно». Я про то, в каком месте правильно поставить «оба», невзирая на то, что в русском тут «оба» говорить вообще не стоит.
              • +1
                Правильно поставить в виде союза «и», поскольку это переводится в данном контектсте именно так. Ни «оба», ни «одновременно» здесь не применимы. В крайнем случае можно допустить союз «как… так и...».

                both A and B:

                одновременно А и Б
                оба А и Б
                как А, так и Б — ok
                и А, и Б — ок
                А и Б — ok

                Некто мог проявить сперва отзывчивость, а немного спустя профессионализм, и всё равно мы скажем «X was both forthcoming and professional», а вот что это было одновременно, сказать не сможем.
                • +1
                  Конечно, конечно. Со всем согласен, везде подпишусь. Только это все совсем не по теме коммента, потому что в посте было переведено как «оба проявили», что вообще не верно. И в комменте я указал именно на использование слова both («оба»). В моем переводе, как вы заметили — ваш вариант.
                • 0
                  Спасибо за замечания. Исправил.
  • 0
    Многие форумы на движках phpbb и IPB страдали такой багой. Модераторы очень удивлялись, видя совершенно левые IP у сообщений )
  • +5
    Счетчики mail.ru страдали от этого, накручивать уники можно было подставляя разные X-Forwarded-For
  • +6
    Напомнило пост о краже денег с яндекса habrahabr.ru/post/74263/
    — Автор поста: В истории заходов фигурирует ip-адрес 127.0.0.1 — это внутренний адрес внутри вашей компании. К письму прилагаю скриншот и прошу объяснить, как можно зайти на Яндекс.Деньги с этого ip-адреса и сделать перевод. Заранее спасибо за ответ.
    Яндекс: IP-адрес 127.0.0.1 — это собственный адрес Вашего компьютера.
    Яндекс (чуть позже): При заходе через анонимный прокси-сервер адрес, показываемый в истории заходов, берётся из заголовка Forwarded-for. Скрипт, определяющий айпи-адрес входящего, был перенаправлен на самого себя и поэтому определил свой адрес. Однако у нас хранится информация обо всех айпи-адресах, с которых совершаются платежи (разумеется, в случае с прокси это будет адрес прокси). По запросу из милиции мы предоставим эту информацию. Сам прокси-сервер также хранит информацию о том, с каких адресов были заходы на него, и получить эту информацию также сможет милиция

    • 0
      Кстати было интересно узнать, как милиция узнает логи прокси сервера, если например он находится в Гренландии и логи там чистятся + все это еще было обернуто в какую нить VPN или вообще через TOR еще пропущено.
  • 0
    Эта бага очень популярная. Даже в документации PHP в комментариях рекомендуется «правильный» способ получения IP с «учётом всех заголовков». Грешен, сам подставлял левые IP своим сообщениям на некоторых форумах.
  • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    А зачем вообще был нужен HTTP прокси? SSH же сам работает как socks прокси.
    В настройках туннеля надо только было поставить Dynamic вместо Local.
  • 0
    Блин, проблема и не в PHP и не в ASP. Проблема в разработчиках.
    Во-перавх полагаться только на ip адрес при оформлении доступа к админке — безоговорочная глупость.
    Во-вторых доверять информацию об IP адресе пользовательскому заголовку.
    Так накосячить можно вообще в любом web приложении.
  • 0
    простите, но разве в таких постах не требуется указать первоисточник или я что-то проглядел?
    src: blog.ircmaxell.com/2012/11/anatomy-of-attack-how-i-hacked.html
    • 0
      Топики-переводы внизу содержат ссылку на источник (рядом с ником автора топика). В данном случае — ссылка с анкором «Anthony Ferrara».
      • 0
        действительно проглядел.

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