XSS'им iOS устройства на примере софта от Facebook, Google, ВКонтакте

    Данный фиче-баг схож с историй про отправку сообщения в Facebook от любого юзера — известен, но не получил широкую огласку. Получилось так, что нашел я его сам, а уже потом нашел информацию о нём в интернетах. Но обо всем по порядку...

    # intro


    Темной, холодной и дождливой Питерской ночью обнаружил я забавный баг, которому оказались подвержены приложения от Facebook, Google, ВКонтакте и скорее всего, от многих других производителей. Для его объяснения нам просто необходимо знать немного теории.

    1/2 Идеология iOS

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

    2/2 Про HTTP

    Протокол HTTP очень прост и использует самую очевидную модель. Всё передается обычным plain текстом. Запрос/ответ обязательно содержит заголовок (header) и (возможно) тело (body). Разделены они через обычный перенос строки (пустую строку). Пример запроса для открытия habrahabr.ru:

    GET / HTTP/1.1
    Host: habrahabr.ru
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Connection: keep-alive
    

    Ответ:
    HTTP/1.1 200 OK
    Server: nginx
    Date: Tue, 19 Nov 2013 13:48:02 GMT
    Content-Type: text/html; charset=UTF-8
    Transfer-Encoding: chunked
    Connection: keep-alive
    Keep-Alive: timeout=25
    X-Powered-By: PHP/5.4.21
    X-Frame-Options: SAMEORIGIN
    Content-Encoding: gzip
    
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
      <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <meta name = "viewport" content = "width = 1080">
        <title>Лучшие за сутки / Посты / Хабрахабр</title>
    ...
    </html>
    

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

    Content-Disposition: attachment
    

    Который описан в RFC 2183 следующим образом
    2.2 The Attachment Disposition Type

    Bodyparts can be designated `attachment' to indicate that they are
    separate from the main body of the mail message, and that their
    display should not be automatic
    , but contingent upon some further
    action of the user. The MUA might instead present the user of a
    bitmap terminal with an iconic representation of the attachments, or,
    on character terminals, with a list of attachments from which the
    user could select for viewing or storage.

    В типичном браузере это выглядит так, что вы обращаетесь к файлу, а он не отображается (как вы привыкли) а предлагает его сохранить (their display should not be automatic).

    # exploit


    А теперь давайте соединим два момента выше. Мы обращаемся на устройстве с iOS к файлу, у которого Content-Disposition: attachment. Получается противоречие. Вроде файл надо сохранить (как обычно и привыкли юзеры, видеть окно сохранения на устройство), но и сделать этого нельзя — ведь возможности такой то и нет. Что же сделали в Apple? Они просто игнорируют в мобильном Safari Content-Disposition и отображают файл в браузере.
    Что с мобильными приложениями? В клиентах FB, Gmail, VK, везде есть вложения в сообщения. Если отправить, например, html или svg файл, то вызывается компонент webview (читать как Safari) который его и рендерит.

    xss.svg
    <?xml version="1.0" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    
    <svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
       <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
       <script type="text/javascript">
       alert('Redirect to google.ru...');
       document.location="http://google.ru";
       </script>
    </svg>
    

    В итоге, Apple, пытаясь обезопасить и пытаясь улучшить жизнь своим пользователям создала неочевидный момент для разработчиков iOS и, всё-таки, снижение безопасности. Никаких уведомлений, что данный контент будет показан мгновенно. Возвращаясь к RFC, было бы достаточно обычного уведомления что-то типа: «данный контент должен быть сохранён, но он будет показан в браузере», но ничего подобного мы не видим. Исключение все же есть только в одном варианте — Facebook, мобильная версия.

    # demo


    GMail
    Facebook
    VK

    # impact


    Как можно заметить, javascript выполняется на другом домене, отличным от основного. Этот домен предназначен только для вложений в сообщения и полностью изолирован от основного сайта. Поэтому реакция, например, Google на это — именно такая (т.е. никакая)
    The domain in which you're triggering the XSS — googleuserconent.com — is specifically meant as a compartmentalized «sandbox» for various types of potentially unsafe, user-controlled content. This domain is isolated from any sensitive content due to the same-origin policy.

    Что и верно. Например на нём можно и в обычном браузере выполнить XSS.

    Но есть другие вектора — фишинг или DoS (например с 0day эксплойтом, который задевает все(?) версии iOS — habrahabr.ru/company/dsec/blog/201602). Да и не все выносят upload контент на отдельные домены (и вот тут уже impact как от полноценной xss на основном домене). Стоит отметить, что нужен именно отдельный домен, а не поддомен.

    В общем, будьте осторожны при открытии вложений на IOS устройствах и при разработке веб-приложений с вложениями. Ведь данный фиче-баг прекрасно воспроизведется и в любом браузере iOS (ведь все они за основу используют Safari).
    • +55
    • 17,5k
    • 3
    Digital Security 182,01
    Безопасность как искусство
    Поделиться публикацией
    Комментарии 3
    • +3
      Почему-то такой код не работает во вконтакте:

         <script type="text/javascript">
         var allcookies = document.cookie;
         alert("All Cookies : " + allcookies );
         </script>
      


      Хотя и там в контексте поддомена на котором кук нет.
      • 0
        iOS уже не торт.
        • 0
          Я сразу увидел Ваше сообщение, всё времени нет посмотреть детально. Алерта и правда нет, думаю на выходных еще посмотрю.

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

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