From 4c3c64a34a506de02073560ba6165e9c542a3902 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 6 May 2023 14:51:28 +0800 Subject: [PATCH] Fix: potential token time attack --- hub/route/server.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hub/route/server.go b/hub/route/server.go index 8768a5c..66a5907 100644 --- a/hub/route/server.go +++ b/hub/route/server.go @@ -2,11 +2,13 @@ package route import ( "bytes" + "crypto/subtle" "encoding/json" "net" "net/http" "strings" "time" + "unsafe" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" @@ -96,6 +98,12 @@ func Start(addr string, secret string) { } } +func safeEuqal(a, b string) bool { + aBuf := unsafe.Slice(unsafe.StringData(a), len(a)) + bBuf := unsafe.Slice(unsafe.StringData(b), len(b)) + return subtle.ConstantTimeCompare(aBuf, bBuf) == 1 +} + func authentication(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { if serverSecret == "" { @@ -106,7 +114,7 @@ func authentication(next http.Handler) http.Handler { // Browser websocket not support custom header if websocket.IsWebSocketUpgrade(r) && r.URL.Query().Get("token") != "" { token := r.URL.Query().Get("token") - if token != serverSecret { + if !safeEuqal(token, serverSecret) { render.Status(r, http.StatusUnauthorized) render.JSON(w, r, ErrUnauthorized) return @@ -119,7 +127,7 @@ func authentication(next http.Handler) http.Handler { bearer, token, found := strings.Cut(header, " ") hasInvalidHeader := bearer != "Bearer" - hasInvalidSecret := !found || token != serverSecret + hasInvalidSecret := !found || !safeEuqal(token, serverSecret) if hasInvalidHeader || hasInvalidSecret { render.Status(r, http.StatusUnauthorized) render.JSON(w, r, ErrUnauthorized)