History

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

Michael Niedermayer committed 1 year ago

Commit 91d96dc1 parent c733e2b2 files · +57 −0Browse files

Unified · Split

2 files
  1. doc/demuxers.texi +7 −0
  2. libavformat/hls.c +50 −0
doc/demuxers.texi+7−0
@@ -564,6 +564,13 @@ prefer to use #EXT-X-START if it's in playlist instead of live_start_index. · 563 unmodified lines
564@item allowed_extensions564@item allowed_extensions
565',' separated list of file extensions that hls is allowed to access.565',' separated list of file extensions that hls is allowed to access.
566 566
567@item extension_picky
568This blocks disallowed extensions from probing
569It also requires all available segments to have matching extensions to the format
570except mpegts, which is always allowed.
571It is recommended to set the whitelists correctly instead of depending on extensions
572Enabled by default.
573
567@item max_reload574@item max_reload
568Maximum number of times a insufficient list is attempted to be reloaded.575Maximum number of times a insufficient list is attempted to be reloaded.
569Default value is 1000.576Default value is 1000.
libavformat/hls.c+50−0
@@ -223,6 +223,7 @@ typedef struct HLSContext { · 222 unmodified lines
223 AVDictionary *avio_opts;223 AVDictionary *avio_opts;
224 AVDictionary *seg_format_opts;224 AVDictionary *seg_format_opts;
225 char *allowed_extensions;225 char *allowed_extensions;
226 int extension_picky;
226 int max_reload;227 int max_reload;
227 int http_persistent;228 int http_persistent;
228 int http_multiple;229 int http_multiple;
@@ -731,6 +732,40 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, · 502 unmodified lines
731 return ret;732 return ret;
732}733}
733 734
735static int test_segment(AVFormatContext *s, const AVInputFormat *in_fmt, struct playlist *pls, struct segment *seg)
736{
737 HLSContext *c = s->priv_data;
738 int matchA = 3;
739 int matchF = 0;
740
741 if (!c->extension_picky)
742 return 0;
743
744 if (strcmp(c->allowed_extensions, "ALL"))
745 matchA = av_match_ext (seg->url, c->allowed_extensions)
746 + 2*(ff_match_url_ext(seg->url, c->allowed_extensions) > 0);
747
748 if (!matchA) {
749 av_log(s, AV_LOG_ERROR, "URL %s is not in allowed_extensions\n", seg->url);
750 return AVERROR_INVALIDDATA;
751 }
752
753 if (in_fmt) {
754 if (in_fmt->extensions) {
755 matchF = av_match_ext( seg->url, in_fmt->extensions)
756 + 2*(ff_match_url_ext(seg->url, in_fmt->extensions) > 0);
757 } else if (!strcmp(in_fmt->name, "mpegts"))
758 matchF = 3;
759
760 if (!(matchA & matchF)) {
761 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);
762 return AVERROR_INVALIDDATA;
763 }
764 }
765
766 return 0;
767}
768
734static int parse_playlist(HLSContext *c, const char *url,769static int parse_playlist(HLSContext *c, const char *url,
735 struct playlist *pls, AVIOContext *in)770 struct playlist *pls, AVIOContext *in)
736{771{
@@ -989,6 +1024,14 @@ static int parse_playlist(HLSContext *c, const char *url, · 252 unmodified lines
989 goto fail;1024 goto fail;
990 }1025 }
991 1026
1027 ret = test_segment(c->ctx, pls->ctx ? pls->ctx->iformat : NULL, pls, seg);
1028 if (ret < 0) {
1029 av_free(seg->url);
1030 av_free(seg->key);
1031 av_free(seg);
1032 goto fail;
1033 }
1034
992 if (duration < 0.001 * AV_TIME_BASE) {1035 if (duration < 0.001 * AV_TIME_BASE) {
993 av_log(c->ctx, AV_LOG_WARNING, "Cannot get correct #EXTINF value of segment %s,"1036 av_log(c->ctx, AV_LOG_WARNING, "Cannot get correct #EXTINF value of segment %s,"
994 " set to default value to 1ms.\n", seg->url);1037 " set to default value to 1ms.\n", seg->url);
@@ -2114,6 +2157,11 @@ static int hls_read_header(AVFormatContext *s) · 1119 unmodified lines
2114 pls->ctx->interrupt_callback = s->interrupt_callback;2157 pls->ctx->interrupt_callback = s->interrupt_callback;
2115 url = av_strdup(pls->segments[0]->url);2158 url = av_strdup(pls->segments[0]->url);
2116 ret = av_probe_input_buffer(&pls->pb.pub, &in_fmt, url, NULL, 0, 0);2159 ret = av_probe_input_buffer(&pls->pb.pub, &in_fmt, url, NULL, 0, 0);
2160
2161 for (int n = 0; n < pls->n_segments; n++)
2162 if (ret >= 0)
2163 ret = test_segment(s, in_fmt, pls, pls->segments[n]);
2164
2117 if (ret < 0) {2165 if (ret < 0) {
2118 /* Free the ctx - it isn't initialized properly at this point,2166 /* Free the ctx - it isn't initialized properly at this point,
2119 * so avformat_close_input shouldn't be called. If2167 * so avformat_close_input shouldn't be called. If
@@ -2576,6 +2624,8 @@ static const AVOption hls_options[] = { · 456 unmodified lines
2576 OFFSET(allowed_extensions), AV_OPT_TYPE_STRING,2624 OFFSET(allowed_extensions), AV_OPT_TYPE_STRING,
2577 {.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"},2625 {.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"},
2578 INT_MIN, INT_MAX, FLAGS},2626 INT_MIN, INT_MAX, FLAGS},
2627 {"extension_picky", "Be picky with all extensions matching",
2628 OFFSET(extension_picky), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS},
2579 {"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded",2629 {"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded",
2580 OFFSET(max_reload), AV_OPT_TYPE_INT, {.i64 = 3}, 0, INT_MAX, FLAGS},2630 OFFSET(max_reload), AV_OPT_TYPE_INT, {.i64 = 3}, 0, INT_MAX, FLAGS},
2581 {"m3u8_hold_counters", "The maximum number of times to load m3u8 when it refreshes without new segments",2631 {"m3u8_hold_counters", "The maximum number of times to load m3u8 when it refreshes without new segments",

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t