Skip to content

Commit 954c9f4

Browse files
authored
Merge pull request #55 from sev-2/fix/security-issue
fix(security) ddos potencial
2 parents d2f45d1 + c342d06 commit 954c9f4

File tree

4 files changed

+108
-15
lines changed

4 files changed

+108
-15
lines changed

controller.go

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -710,9 +710,32 @@ func StorageProxy(appCtx Context, bucketName string, routePath string) error {
710710
// Default Proxy Handler
711711
var proxyLogger = logger.HcLog().Named("raiden.controller.proxy")
712712

713-
func ProxyHandler(
714-
targetURL *url.URL,
715-
basePath string,
713+
// reference path from https://github.com/supabase/auth/blob/master/openapi.yaml
714+
var allowedAuthPathMap = map[string]bool{
715+
"token": true,
716+
"logout": true,
717+
"verify": true,
718+
"signup": true,
719+
"recover": true,
720+
"resend": true,
721+
"magiclink": true,
722+
"otp": true,
723+
"user": true,
724+
"reauthenticate": true,
725+
"factors": true,
726+
"authorize": true,
727+
"callback": true,
728+
"sso": true,
729+
"saml": true,
730+
"invite": true,
731+
"generate_link": true,
732+
"admin": true,
733+
"settings": true,
734+
"health": true,
735+
}
736+
737+
func AuthProxy(
738+
config *Config,
716739
requestInterceptor func(req *fasthttp.Request),
717740
responseInterceptor func(resp *fasthttp.Response) error,
718741
) fasthttp.RequestHandler {
@@ -723,15 +746,24 @@ func ProxyHandler(
723746

724747
// Copy the original request to the new request object
725748
ctx.Request.CopyTo(req)
726-
727-
paths := strings.Split(req.URI().String(), basePath)
749+
paths := strings.Split(req.URI().String(), "/auth/v1")
728750
if len(paths) < 2 {
729751
ctx.Request.Header.SetContentType("application/json")
730752
ctx.SetBodyString("{ \"message\" : \"invalid path\"}")
731753
return
732754
}
733755

734-
proxyUrl := fmt.Sprintf("%s%s%s", targetURL.String(), basePath, paths[1])
756+
// validate sub path
757+
forwardedPath := paths[1]
758+
subPath := strings.Split(forwardedPath, "/")
759+
if _, exist := allowedAuthPathMap[subPath[1]]; !exist {
760+
ctx.Response.SetStatusCode(fasthttp.StatusNotFound)
761+
errResponse := "{ \"messages\": \"resource not found\"}"
762+
ctx.Response.SetBodyString(errResponse)
763+
return
764+
}
765+
766+
proxyUrl := fmt.Sprintf("%s/auth/v1%s", config.SupabasePublicUrl, forwardedPath)
735767
req.SetRequestURI(proxyUrl)
736768

737769
resp := fasthttp.AcquireResponse()

controller_test.go

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/json"
55
"errors"
66
"fmt"
7-
"net/url"
87
"testing"
98

109
"github.com/sev-2/raiden"
@@ -302,14 +301,17 @@ func TestStorageController(t *testing.T) {
302301
assert.NoError(t, storage.AfterHead(ctx))
303302
}
304303

305-
// Test ProxyHandler
306-
func TestProxyHandler(t *testing.T) {
307-
ctx := newMockCtx()
308-
targetURL, _ := url.Parse("http://example.com")
304+
// Test AuthProxy
305+
func TestAuthProxy(t *testing.T) {
306+
ctx := &mock.MockContext{
307+
RequestCtx: &fasthttp.RequestCtx{},
308+
ConfigFn: func() *raiden.Config {
309+
return &raiden.Config{SupabasePublicUrl: "/"}
310+
},
311+
}
309312

310-
handler := raiden.ProxyHandler(
311-
targetURL,
312-
"/",
313+
handler := raiden.AuthProxy(
314+
ctx.Config(),
313315
func(req *fasthttp.Request) {},
314316
func(resp *fasthttp.Response) error { return nil },
315317
)
@@ -319,6 +321,64 @@ func TestProxyHandler(t *testing.T) {
319321
assert.Equal(t, fasthttp.StatusOK, ctx.Response.StatusCode())
320322
}
321323

324+
// Test AuthProxy
325+
func TestAuthProxy_ActualCallWithoutMock(t *testing.T) {
326+
ctx := &mock.MockContext{
327+
RequestCtx: &fasthttp.RequestCtx{},
328+
ConfigFn: func() *raiden.Config {
329+
return &raiden.Config{SupabasePublicUrl: "/"}
330+
},
331+
}
332+
333+
handler := raiden.AuthProxy(
334+
ctx.Config(),
335+
func(req *fasthttp.Request) {},
336+
func(resp *fasthttp.Response) error { return nil },
337+
)
338+
339+
ctx.Request.SetRequestURI("/auth/v1/signup")
340+
handler(ctx.RequestCtx)
341+
assert.Equal(t, fasthttp.StatusInternalServerError, ctx.Response.StatusCode())
342+
}
343+
344+
func TestAuthProxy_NotAllowedPath(t *testing.T) {
345+
ctx := &mock.MockContext{
346+
RequestCtx: &fasthttp.RequestCtx{},
347+
ConfigFn: func() *raiden.Config {
348+
return &raiden.Config{SupabasePublicUrl: "/"}
349+
},
350+
}
351+
352+
handler := raiden.AuthProxy(
353+
ctx.Config(),
354+
func(req *fasthttp.Request) {},
355+
func(resp *fasthttp.Response) error { return nil },
356+
)
357+
358+
ctx.Request.SetRequestURI("/auth/v1/anymore")
359+
handler(ctx.RequestCtx)
360+
assert.Equal(t, fasthttp.StatusNotFound, ctx.Response.StatusCode())
361+
}
362+
363+
func TestAuthProxy_AllowedWithSpecificPath(t *testing.T) {
364+
ctx := &mock.MockContext{
365+
RequestCtx: &fasthttp.RequestCtx{},
366+
ConfigFn: func() *raiden.Config {
367+
return &raiden.Config{SupabasePublicUrl: "/"}
368+
},
369+
}
370+
371+
handler := raiden.AuthProxy(
372+
ctx.Config(),
373+
func(req *fasthttp.Request) {},
374+
func(resp *fasthttp.Response) error { return nil },
375+
)
376+
377+
ctx.Request.SetRequestURI("/auth/v1/saml/metadata")
378+
handler(ctx.RequestCtx)
379+
assert.Equal(t, fasthttp.StatusInternalServerError, ctx.Response.StatusCode())
380+
}
381+
322382
// Test MarshallAndValidate
323383
func TestMarshallAndValidate(t *testing.T) {
324384
ctx := newMockCtx()

pkg/mock/context.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
)
1010

1111
type MockContext struct {
12+
*fasthttp.RequestCtx
1213
CtxFn func() context.Context
1314
SetCtxFn func(ctx context.Context)
1415
ConfigFn func() *raiden.Config

router.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func (r *router) BuildHandler() {
126126
// Proxy auth url
127127
u, err := url.Parse(r.config.SupabasePublicUrl)
128128
if err == nil {
129-
r.engine.ANY("/auth/v1/{path:*}", ProxyHandler(u, "/auth/v1", nil, nil))
129+
r.engine.ANY("/auth/v1/{path:*}", AuthProxy(r.config, nil, nil))
130130

131131
r.engine.GET("/realtime/v1/websocket", func(ctx *fasthttp.RequestCtx) {
132132
WebSocketHandler(ctx, u)

0 commit comments

Comments
 (0)