|
@@ -0,0 +1,142 @@
|
|
|
+From 9803800e0e8cd8e1e7695f77cfbf4e0db0abfe57 Mon Sep 17 00:00:00 2001
|
|
|
+From: Michael Niedermayer <michael@niedermayer.cc>
|
|
|
+Date: Thu, 16 Jan 2025 01:28:46 +0100
|
|
|
+Subject: [PATCH] avformat/hls: Be more picky on extensions
|
|
|
+
|
|
|
+This blocks disallowed extensions from probing
|
|
|
+It also requires all available segments to have matching extensions to the format
|
|
|
+mpegts is treated independent of the extension
|
|
|
+
|
|
|
+It is recommended to set the whitelists correctly
|
|
|
+instead of depending on extensions, but this should help a bit,
|
|
|
+and this is easier to backport
|
|
|
+
|
|
|
+Fixes: CVE-2023-6602 II. HLS Force TTY Demuxer
|
|
|
+Fixes: CVE-2023-6602 IV. HLS XBIN Demuxer DoS Amplification
|
|
|
+
|
|
|
+The other parts of CVE-2023-6602 have been fixed by prior commits
|
|
|
+
|
|
|
+Found-by: Harvey Phillips of Amazon Element55 (element55)
|
|
|
+Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
|
|
|
+(cherry picked from commit 91d96dc8ddaebe0b6cb393f672085e6bfaf15a31)
|
|
|
+Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
|
|
|
+
|
|
|
+CVE: CVE-2023-6602 CVE-2023-6604 CVE-2023-6605
|
|
|
+
|
|
|
+Upstream-Status: Backport [https://github.com/FFmpeg/FFmpeg/commit/9803800e0e8cd8e1e7695f77cfbf4e0db0abfe57]
|
|
|
+
|
|
|
+Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
|
|
|
+---
|
|
|
+ doc/demuxers.texi | 7 +++++++
|
|
|
+ libavformat/hls.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
+ 2 files changed, 57 insertions(+)
|
|
|
+
|
|
|
+diff --git a/doc/demuxers.texi b/doc/demuxers.texi
|
|
|
+index 26ae768..6e0b25e 100644
|
|
|
+--- a/doc/demuxers.texi
|
|
|
++++ b/doc/demuxers.texi
|
|
|
+@@ -365,6 +365,13 @@ segment index to start live streams at (negative values are from the end).
|
|
|
+ @item allowed_extensions
|
|
|
+ ',' separated list of file extensions that hls is allowed to access.
|
|
|
+
|
|
|
++@item extension_picky
|
|
|
++This blocks disallowed extensions from probing
|
|
|
++It also requires all available segments to have matching extensions to the format
|
|
|
++except mpegts, which is always allowed.
|
|
|
++It is recommended to set the whitelists correctly instead of depending on extensions
|
|
|
++Enabled by default.
|
|
|
++
|
|
|
+ @item max_reload
|
|
|
+ Maximum number of times a insufficient list is attempted to be reloaded.
|
|
|
+ Default value is 1000.
|
|
|
+diff --git a/libavformat/hls.c b/libavformat/hls.c
|
|
|
+index d5e9b21..e1bb677 100644
|
|
|
+--- a/libavformat/hls.c
|
|
|
++++ b/libavformat/hls.c
|
|
|
+@@ -214,6 +214,7 @@ typedef struct HLSContext {
|
|
|
+ AVDictionary *avio_opts;
|
|
|
+ AVDictionary *seg_format_opts;
|
|
|
+ char *allowed_extensions;
|
|
|
++ int extension_picky;
|
|
|
+ int max_reload;
|
|
|
+ int http_persistent;
|
|
|
+ int http_multiple;
|
|
|
+@@ -716,6 +717,40 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url,
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
++static int test_segment(AVFormatContext *s, const AVInputFormat *in_fmt, struct playlist *pls, struct segment *seg)
|
|
|
++{
|
|
|
++ HLSContext *c = s->priv_data;
|
|
|
++ int matchA = 3;
|
|
|
++ int matchF = 0;
|
|
|
++
|
|
|
++ if (!c->extension_picky)
|
|
|
++ return 0;
|
|
|
++
|
|
|
++ if (strcmp(c->allowed_extensions, "ALL"))
|
|
|
++ matchA = av_match_ext (seg->url, c->allowed_extensions)
|
|
|
++ + 2*(ff_match_url_ext(seg->url, c->allowed_extensions) > 0);
|
|
|
++
|
|
|
++ if (!matchA) {
|
|
|
++ av_log(s, AV_LOG_ERROR, "URL %s is not in allowed_extensions\n", seg->url);
|
|
|
++ return AVERROR_INVALIDDATA;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (in_fmt) {
|
|
|
++ if (in_fmt->extensions) {
|
|
|
++ matchF = av_match_ext( seg->url, in_fmt->extensions)
|
|
|
++ + 2*(ff_match_url_ext(seg->url, in_fmt->extensions) > 0);
|
|
|
++ } else if (!strcmp(in_fmt->name, "mpegts"))
|
|
|
++ matchF = 3;
|
|
|
++
|
|
|
++ if (!(matchA & matchF)) {
|
|
|
++ av_log(s, AV_LOG_ERROR, "detected format extension %s mismatches allowed extensions in url %s\n", in_fmt->extensions ? in_fmt->extensions : "none", seg->url);
|
|
|
++ return AVERROR_INVALIDDATA;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
+ static int parse_playlist(HLSContext *c, const char *url,
|
|
|
+ struct playlist *pls, AVIOContext *in)
|
|
|
+ {
|
|
|
+@@ -959,6 +994,14 @@ static int parse_playlist(HLSContext *c, const char *url,
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
++ ret = test_segment(c->ctx, pls->ctx ? pls->ctx->iformat : NULL, pls, seg);
|
|
|
++ if (ret < 0) {
|
|
|
++ av_free(seg->url);
|
|
|
++ av_free(seg->key);
|
|
|
++ av_free(seg);
|
|
|
++ goto fail;
|
|
|
++ }
|
|
|
++
|
|
|
+ if (duration < 0.001 * AV_TIME_BASE) {
|
|
|
+ av_log(c->ctx, AV_LOG_WARNING, "Cannot get correct #EXTINF value of segment %s,"
|
|
|
+ " set to default value to 1ms.\n", seg->url);
|
|
|
+@@ -2040,6 +2083,11 @@ static int hls_read_header(AVFormatContext *s)
|
|
|
+ pls->ctx->interrupt_callback = s->interrupt_callback;
|
|
|
+ url = av_strdup(pls->segments[0]->url);
|
|
|
+ ret = av_probe_input_buffer(&pls->pb.pub, &in_fmt, url, NULL, 0, 0);
|
|
|
++
|
|
|
++ for (int n = 0; n < pls->n_segments; n++)
|
|
|
++ if (ret >= 0)
|
|
|
++ ret = test_segment(s, in_fmt, pls, pls->segments[n]);
|
|
|
++
|
|
|
+ if (ret < 0) {
|
|
|
+ /* Free the ctx - it isn't initialized properly at this point,
|
|
|
+ * so avformat_close_input shouldn't be called. If
|
|
|
+@@ -2467,6 +2515,8 @@ static const AVOption hls_options[] = {
|
|
|
+ OFFSET(allowed_extensions), AV_OPT_TYPE_STRING,
|
|
|
+ {.str = "3gp,aac,avi,ac3,eac3,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav"},
|
|
|
+ INT_MIN, INT_MAX, FLAGS},
|
|
|
++ {"extension_picky", "Be picky with all extensions matching",
|
|
|
++ OFFSET(extension_picky), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS},
|
|
|
+ {"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded",
|
|
|
+ OFFSET(max_reload), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, FLAGS},
|
|
|
+ {"m3u8_hold_counters", "The maximum number of times to load m3u8 when it refreshes without new segments",
|
|
|
+--
|
|
|
+2.40.0
|