From 1fa53b49d41d3f4f51652f67fb2f918a9ee981fe Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Sun, 23 Jul 2023 20:18:58 +0200 Subject: [PATCH] webrtc, hls: prevent brute-force attacks by waiting before sending responses (#2100) --- internal/core/hls_http_server.go | 9 +++++++++ internal/core/rtmp_conn.go | 6 +++--- internal/core/rtsp_conn.go | 4 ++-- internal/core/webrtc_http_server.go | 5 +++++ internal/core/webrtc_manager.go | 1 + internal/core/webrtc_session.go | 9 +++++++++ 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/internal/core/hls_http_server.go b/internal/core/hls_http_server.go index b6bc76c7..3f487a8b 100644 --- a/internal/core/hls_http_server.go +++ b/internal/core/hls_http_server.go @@ -7,6 +7,7 @@ import ( "net/http" gopath "path" "strings" + "time" "github.com/gin-gonic/gin" @@ -14,6 +15,10 @@ import ( "github.com/bluenviron/mediamtx/internal/logger" ) +const ( + hlsPauseAfterAuthError = 2 * time.Second +) + //go:embed hls_index.html var hlsIndex []byte @@ -166,6 +171,10 @@ func (s *hlsHTTPServer) onRequest(ctx *gin.Context) { remoteAddr := net.JoinHostPort(ip, port) s.Log(logger.Info, "connection %v failed to authenticate: %v", remoteAddr, terr.message) + + // wait some seconds to stop brute force attacks + <-time.After(hlsPauseAfterAuthError) + ctx.Writer.WriteHeader(http.StatusUnauthorized) return } diff --git a/internal/core/rtmp_conn.go b/internal/core/rtmp_conn.go index 75d33df1..39fe99c3 100644 --- a/internal/core/rtmp_conn.go +++ b/internal/core/rtmp_conn.go @@ -30,7 +30,7 @@ import ( ) const ( - rtmpConnPauseAfterAuthError = 2 * time.Second + rtmpPauseAfterAuthError = 2 * time.Second ) func pathNameAndQuery(inURL *url.URL) (string, url.Values, string) { @@ -367,7 +367,7 @@ func (c *rtmpConn) runRead(ctx context.Context, u *url.URL) error { if res.err != nil { if terr, ok := res.err.(*errAuthentication); ok { // wait some seconds to stop brute force attacks - <-time.After(rtmpConnPauseAfterAuthError) + <-time.After(rtmpPauseAfterAuthError) return terr } return res.err @@ -782,7 +782,7 @@ func (c *rtmpConn) runPublish(u *url.URL) error { if res.err != nil { if terr, ok := res.err.(*errAuthentication); ok { // wait some seconds to stop brute force attacks - <-time.After(rtmpConnPauseAfterAuthError) + <-time.After(rtmpPauseAfterAuthError) return terr } return res.err diff --git a/internal/core/rtsp_conn.go b/internal/core/rtsp_conn.go index 48178291..e8d64175 100644 --- a/internal/core/rtsp_conn.go +++ b/internal/core/rtsp_conn.go @@ -17,7 +17,7 @@ import ( ) const ( - rtspConnPauseAfterAuthError = 2 * time.Second + rtspPauseAfterAuthError = 2 * time.Second ) type rtspConnParent interface { @@ -204,7 +204,7 @@ func (c *rtspConn) handleAuthError(authErr error) (*base.Response, error) { } // wait some seconds to stop brute force attacks - <-time.After(rtspConnPauseAfterAuthError) + <-time.After(rtspPauseAfterAuthError) return &base.Response{ StatusCode: base.StatusUnauthorized, diff --git a/internal/core/webrtc_http_server.go b/internal/core/webrtc_http_server.go index d5688fa2..136a4359 100644 --- a/internal/core/webrtc_http_server.go +++ b/internal/core/webrtc_http_server.go @@ -10,6 +10,7 @@ import ( "regexp" "strconv" "strings" + "time" "github.com/gin-gonic/gin" "github.com/google/uuid" @@ -318,6 +319,10 @@ func (s *webRTCHTTPServer) onRequest(ctx *gin.Context) { } s.Log(logger.Info, "connection %v failed to authenticate: %v", remoteAddr, terr.message) + + // wait some seconds to stop brute force attacks + <-time.After(webrtcPauseAfterAuthError) + ctx.Writer.WriteHeader(http.StatusUnauthorized) return } diff --git a/internal/core/webrtc_manager.go b/internal/core/webrtc_manager.go index c9ae1230..3d3ec2eb 100644 --- a/internal/core/webrtc_manager.go +++ b/internal/core/webrtc_manager.go @@ -23,6 +23,7 @@ import ( ) const ( + webrtcPauseAfterAuthError = 2 * time.Second webrtcHandshakeTimeout = 10 * time.Second webrtcTrackGatherTimeout = 2 * time.Second webrtcPayloadMaxSize = 1188 // 1200 - 12 (RTP header) diff --git a/internal/core/webrtc_session.go b/internal/core/webrtc_session.go index 8bc9d03c..70dd92ba 100644 --- a/internal/core/webrtc_session.go +++ b/internal/core/webrtc_session.go @@ -240,8 +240,12 @@ func (s *webRTCSession) runPublish() (int, error) { }) if res.err != nil { if _, ok := res.err.(*errAuthentication); ok { + // wait some seconds to stop brute force attacks + <-time.After(webrtcPauseAfterAuthError) + return http.StatusUnauthorized, res.err } + return http.StatusBadRequest, res.err } @@ -363,11 +367,16 @@ func (s *webRTCSession) runRead() (int, error) { }) if res.err != nil { if _, ok := res.err.(*errAuthentication); ok { + // wait some seconds to stop brute force attacks + <-time.After(webrtcPauseAfterAuthError) + return http.StatusUnauthorized, res.err } + if strings.HasPrefix(res.err.Error(), "no one is publishing") { return http.StatusNotFound, res.err } + return http.StatusBadRequest, res.err }