avformat/rtsp: clear authentication on cross-origin redirects

RTSP redirects retain URL credentials and authentication state when a
Location URI changes to another origin. This can forward reusable
credentials to a server with a different scheme, host, or port.

Clear the stored credentials and authentication state when the redirect
crosses an origin boundary. Preserve them for same-origin redirects.

Fixes: cross-origin credential disclosure
Fixes: rtsp_redirect_auth_leak_poc.py
Fixes: VaKaPOnfN02z
(cherry picked from commit a441a2eb38)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Abdessamie
2026-07-22 06:21:26 +02:00
committed by Michael Niedermayer
parent 9bece37c53
commit 63cfa99169

View File

@@ -1868,6 +1868,32 @@ void ff_rtsp_close_connections(AVFormatContext *s)
ffurl_closep(&rt->rtsp_hd);
}
static int rtsp_url_same_origin(const char *url1, const char *url2)
{
char proto1[128], proto2[128];
char host1[1024], host2[1024];
int port1, port2;
av_url_split(proto1, sizeof(proto1), NULL, 0, host1, sizeof(host1),
&port1, NULL, 0, url1);
av_url_split(proto2, sizeof(proto2), NULL, 0, host2, sizeof(host2),
&port2, NULL, 0, url2);
if (!proto1[0] || !proto2[0] || !host1[0] || !host2[0])
return 0;
if (port1 < 0)
port1 = !av_strcasecmp(proto1, "rtsps") ? RTSPS_DEFAULT_PORT
: RTSP_DEFAULT_PORT;
if (port2 < 0)
port2 = !av_strcasecmp(proto2, "rtsps") ? RTSPS_DEFAULT_PORT
: RTSP_DEFAULT_PORT;
return !av_strcasecmp(proto1, proto2) &&
!av_strcasecmp(host1, host2) &&
port1 == port2;
}
int ff_rtsp_connect(AVFormatContext *s)
{
RTSPState *rt = s->priv_data;
@@ -2181,7 +2207,13 @@ redirect:
ff_rtsp_close_streams(s);
ff_rtsp_close_connections(s);
if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
int ret = ff_format_check_set_url(s, reply->location);
int ret;
if (!rtsp_url_same_origin(s->url, reply->location)) {
memset(rt->auth, 0, sizeof(rt->auth));
memset(&rt->auth_state, 0, sizeof(rt->auth_state));
}
ret = ff_format_check_set_url(s, reply->location);
if (ret < 0) {
err = ret;
goto fail2;