company_banner

Как защитить своих пользователей

    100 миллиардов долларов США – огромная сумма, не правда ли? Именно во столько оценивают мировой рынок интернет-рекламы в 2012 году. Не надо далеко ходить, чтобы понять, кто получит большую часть этих денег. Конечно же, это такие компании, как Google, Facebook, Yahoo! и т.д. Но примерно 20% от этой суммы получат спамеры. Эти огромные деньги привлекают очень хорошо организованный бизнес и талантливых людей.

    image

    До появления Facebook, Одноклассников, ВКонтакте и других социальных сетей почта была самым популярным способом распространения спама. Но сейчас социальные сети предлагают огромный спектр инструментов для распространения назойливой рекламы в обход официальных каналов. Я не буду вдаваться в подробности о каждом из них, это не является темой данного поста, я просто перечислю те, с которыми мы сталкиваемся в Одноклассниках.

    Первый и, пожалуй, самый главный – это спам через личные сообщения. Нет ничего проще, чем отправить сообщение в социальной сети, не правда ли?

    Второй – через комментарии к различным объектам (фотографии, видео и т.д.).

    Третий – приглашения в спамерские группы, либо создание соответствующих новостей и тем в обычных группах.

    Четвертый – спам на фотографиях, т.е. когда рекламное сообщение пишут на фотографии и затем загружают её на сайт.

    Пятая разновидность у нас условно называется «Эроклассницы». Устанавливают аккаунту фотографию привлекательной особы в полуобнаженном виде, ставят соответствующий статус либо добавляют фотографии с мусорной рекламой, и начинают ходить в гости.

    Учитывая массовость социальных сетей, неудивительно, что главной ценностью для спамеров являются уже не адреса электронной почты, а активированные аккаунты с правом посылать сообщения, размещать фотографии и устанавливать статусы. Как же спамеру получить столько аккаунтов? Ведь автоматические регистрации во всех основных социальных сетях не работают, так как для активации аккаунта требуется номер телефона. Ответ на этот вопрос прост – использовать аккаунты обычных людей. Но как получить к ним доступ?

    К сожалению, многие из проблем, связанные с незаконным использованием аккаунтов, не могут быть решены на стороне разработчиков сервиса, так как причиной их возникновения является низкий уровень подготовки пользователей. Многие просто-напросто не знают, что небезопасно ставить простые пароли, что не стоит качать и устанавливать программное обеспечение неизвестных производителей, что не надо жать галочку «запомнить пароль», заходя на сайт с публично доступных компьютеров. Единственное, что может сделать разработчик – это принудительно заставлять использовать сложные пароли и давать рекомендации по безопасности, повышая уровень подготовки пользователей. Но все эти проблемы – только верхушка айсберга, и никогда не приведут к массовым кражамаккаунтов. Существуют проблемы, куда более опасные для пользователей — например, низкий уровень квалификации программиста, который разрабатывал сервис, либо недостаточно хорошо поставленный процесс тестирования. Как раз о таких проблемах и пойдет речь в данном посте.

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

    Cross-site scripting

    Одна из часто встречающихся уязвимостей, позволяющая внедрить свой собственный код в тело документа.

    Как ее использовать:
    • можно украсть cookies или другие пользовательские данные;
    • можно изменять внешний вид и поведение сайта;
    • можно выполнять действия от имени пользователя (открывать окна, посылать сообщения и т.д.).


    К сожалению, эта беда не обошла наш ресурс: был найден целый ряд уязвимостей этого типа, но все они уже закрыты. Такие ошибки возникают при небрежном отношении к выводу данных, предоставленных пользователем.

    Пример 1:
    Данные, введенные пользователем: name = “Вася /> Пупкин”;
    Как осуществляется вывод данных: ${name}

    Когда мы выводим пользовательский контент непосредственно в тело DOM-документа, мы легко можем попасть в ситуацию, при которой браузер воспримет HTML-код в выводимой строке как код, а не как строку.



    На рисунке видно, что подпись к фотографии изображается в виде HTML-объекта селект (я заменил тег скрипт на селект для наглядности). Жертвами этого бага могли стать все, кто открыл фотографию, специально подписанную взломщиком.

    Способ борьбы:
    Внимательно относиться к пользовательским данным, везде при выводе в тело документа эскейпить опасные символы. Подменять & < > " ' на &amp; &lt; &gt; &quot; &#39;

    Пример 2:
    Данные, введенные пользователем: name=”Вася Пупкин '>/ ”;
    Как осуществляется вывод данных:



    Эффект будет такой же, как и в первом примере, способы защиты – те же.

    Пример 3:
    Данные, введенные пользователем: name=”Madonna'); doSomeKillingAndStealing(' ”;
    Как осуществляется вывод данных: Search

    Проблема была в музыкальных статусах: при клике на название артиста можно было подставить свой собственный код.

    Способ борьбы:
    Как и в двух примерах до этого, надо эскейпить опасные символы, но для JavaScript они немного другие. Необходимо при выводе подменять \ / ' " на \\ \/ \' \"

    Главное правило – никогда не доверять пользовательским данным.

    Cookies

    Cookies являются key/value хранилищем в браузере, которое применяется для хранения пользовательских данных между сессиями и идентификатора сессии. По умолчанию доступ к cookies имеет JavaScript, что при наличии приведенных выше уязвимостей делает их достаточно опасным местом для хранения данных. Но прежде чем рассказать, как защитить cookies, я хочу обратить внимание на то, как они устанавливаются.

    Итак, cookies могут устанавливаться как для конкретного домена, для всех поддоменов, так и вообще для всех доменов. Практически всегда нужно устанавливать cookies для конкретного домена. Но иногда бывают случаи, когда необходимо иметь возможность использования данных из cookies при переходе между доменами. Так, например, на Одноклассниках при переходе между основным сайтом и мобильной версией нет необходимости вводить пароль еще раз. Это сделано при помощи установки сессионной cookie на домен ".odnoklassniki.ru". Но за это удобство можно дорого заплатить. Если вдруг появится уязвимый поддомен у odnoklassniki.ru, то можно будет получить доступ к cookie основного портала через этот домен.

    Лучшим способом защитить cookies будет выставление им атрибута HttpOnly. Этот атрибут запрещает доступ к cookies через JavaScript. Такая защита будет работать в 99% случаев, кроме тех, когда взломщик может послать XMLHttpRequest и получить ответ, выставляющий cookies. Тогда, используя метод getAllResponseHeaders, можно получить к ним доступ.

    Но продолжим разговор про пользовательские данные. Данные могут быть не только текстовые, но и в виде файлов. Если ваш сервис позволяет закачивать к себе файлы, то будьте крайне осторожны: необходимо чётко определить те форматы файлов, которые вы позволяете загружать на свои серверы, и при возврате этих файлов выставлять им корректные заголовки. Дальше я расскажу, почему.

    SVG

    Формат векторной графики SVG является одним из опасных форматов для загрузки на серверы. Сам файл может содержать в себе JavaScript. Есть 5 способов валидно подключить его на странице
    • Object
    • Iframe
    • Embed
    • Img
    • CSS background


    Первые 3 способа при подключении будут исполнять содержащийся в файле JavaScript. Сам факт нахождения такого файла на сервере влечет за собой определенную опасность. Ведь злоумышленник личным сообщением может отправить прямую ссылку на файл, открыв который, пользователь исполнит скрипт, находящийся внутри файла.

    SVG – не единственный потенциально опасный формат. Любой Flash- или HTML-документ, загружаемый пользователем, должны складываться на отдельный домен, с которого нет доступа к cookies вашего портала.

    Content and character set sniffing

    Есть у браузеров такая интересная особенность: если контент присланного файла отличается от указанного в заголовке Content-Type, то браузер будет искать по внутренностям файла, какой же на самом деле у него формат. Если вдруг браузер найдет внутри HTML, то файл он интерпретирует именно как HTML. Т.е. если ваш сервис позволяет закачивать файлы в формате JPEGи PNG, а при выводе по какой-либо причине выставляет Content-Type: image/jpeg, то, возвращая PNG-файлы, браузер будет заглядывать внутрь, чтобы понять, какой на самом деле формат файла. Даже если на сервере у вас происходит оптимизация изображений, то это абсолютно не гарантирует вам, что после оптимизации HTML перестанет быть валидным или как-то изменится. Существуют инструменты, позволяющие сформировать изображение таким образом, что после оптимизации HTML внутри файла остается неизменным.
    Дабы избежать проблем, стоит придерживаться 3 основных правил:
    • всегда возвращать файлы с таким Content-Type, который он на самом деле имеет
    • не использовать text/plain и application/octet-stream, т.к. для этих форматов браузеры всегда смотрят что внутри
    • выставить заголовок X-Content-Options: nosniff. Этот заголовок запрещает браузерам заглядывать в контент.


    Clickjacking

    С этой проблемой мы столкнулись около полугода назад, однако неизвестно, насколько она на самом деле стара. Мы узнали о ней из публикации на одном популярном блоге. Смысл атаки на Одноклассников заключался в том, что наш сайт встраивали в iframe на страничке с очень похожим на оригинал доменом. Фрейм растягивали во весь экран. Тогда пользователь, зайдя на вредоносный сайт и будучи авторизированным на нашем сайте, видел свой профиль и пребывал в полной уверенности, что находится на Одноклассниках. В этот момент ему показывали либо окно с просьбой ввести личные данные (логин и пароль), либо платежку для перевода денег. На многих очень популярных сайтах в интернете эта уязвимость есть и по сей день. На Одноклассниках мы её закрыли сразу же, как только о ней узнали.

    Есть два средства борьбы с этой проблемой:
    • заголовок, запрещающий открытие сайта во фрейме (X-FRAME-OPTIONS=DENY)
    • JavaScript-код


    Пример JavaScript, который используется на Одноклассниках:

    try{
         top.location.toString();
         if(top != self) {
             throw new Error(''); 
         }
     } catch(e){
         top.location = location; 
     }
    


    В нашем случае мы не можем использовать заголовок из-за некоторых архитектурных особенностей портала, поэтому защищаемся при помощи JavaScript.

    Cross-site request forgery

    Это одна из самых простых уязвимостей. Она позволяет выполнять действия от имени пользователя, например, посылать сообщения, ставить оценки к фотографиям и т.д. Конечно, на Одноклассниках подобных проблем нет, но на некоторых других известных ресурсах они наблюдаются. В целях безопасности этих ресурсов я не буду озвучивать их названия. Поясню суть этой проблемы на примере: допустим, у вас есть очень популярный форум, и вы хотите знать, кто именно ходит к вам на сайт. Вы можете зарегистрировать аккаунт на Одноклассниках и встроить ссылку на свой профиль в невидимом iframe. Тогда при заходе на ваш форум все авторизированные на Одноклассниках пользователи автоматически зайдут к вам в гости, т.е. выполнят действие похода в гости, сами того не осознавая.

    На этом я, пожалуй, закончу свой немаленький пост. Если кого-то заинтересовала эта тема, вот вам парочка неплохих источников информации:

    Книга — «The Tangled Web» by Michal Zalewski
    www.owasp.org

    Команда Одноклассников
    Mail.ru Group
    Строим Интернет

    Комментарии 7

      0
      Начали статью со спама, потом перешли на взлом аккаунтов, потом перешли к уязвимостям… в середине поста стало даже интересно куда фантазия автора заведет. К сожаления, до квантовой физики и колонизации Марса не дошли. Хочется либо большей цельности, либо уж полной шизы!
        +2
        Нормальный плавный такой переход от водички сверху, к материалу имеющему значение :)
        0
        … что не надо жать галочку «запомнить пароль», заходя на сайт с публично доступных компьютеров
        А что тогда делает вот этот код на первой странице www.odnoklassniki.ru/?
        <input type="checkbox" name="st.remember" checked="checked" id="field_remember">
        
          0
          :-) Очевидно, что если по умолчанию галочку не ставить, то очень много людей так и не воспользуется этой функцией, хотя подсознательно и хотели бы :)
            0
            Тут, как говорится, «или штаны наденьте, или крестик снимите».
            Потому как или весь тот абзац звучал бы красиво (включая "… разработчик не может ничего сделать..."), не будь этой строчки кода.
          0
          Спасибо за статью! У меня вопрос — а если бы стояла задача сделать так, чтобы при переходе из мобильной версии (нативного приложения а не сайта) в веб-версию не надо было логиниться дважды?
            +1
            Используйте одноразовые токены для логина. Т.е. при клике пользователя приложение сперва делает запрос в api, получая одноразовый токен, по которому авторизуется данный пользователь, а потом уже кидает его в браузер, передавая этот токен в урле.

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

          Самое читаемое